Spine.js and select-all checkbox - coffeescript

I'm trying to make tableView with select-all checkbox on spine.js and coffeescript. I cant understand how i can bind select-all click to select all models in table. "select-all" checkbox is rendered at UserList view.
ItemView code:
class UserItem extends Spine.Controller
className: 'user-item'
tag: 'tr'
elements:
'input[type="checkbox"]': 'checkbox'
events:
'click input[type="checkbox"]': 'itemChbClicked'
constructor: ->
super
#item.bind("update", #render)
#item.bind("destroy", #remove)
render: ->
#html require('views/user/item')(#item)
#
remove: =>
#el.remove()
itemChbClicked: (e) ->
#item.selected = #checkbox.is(':checked')
ItemList code:
class UserList extends Spine.Controller
className: 'user-list'
elements:
'.items': 'items'
".select-all": "select_all_chb"
constructor: ->
super
#html require('views/user/list')()
User.bind("create", #addOne)
User.bind("refresh", #addAll)
User.fetch()
addOne: (user) =>
view = new UserItem(item: user)
#items.append(view.render().el)
addAll: =>
User.each(#addOne)
Any help would be appreciated! Thanks!

It looks like you're close. In UserList create the select_all_chb function and have it change the users:
class UserList
select_all_chb: =>
User.each (user) ->
user.selected = true
user.save()
Since you've bound the "change" event to "render", all the checklist items will be redrawn.

Related

Is there a useState concept so I can create a service which holds data that is accessed in multiple components?

I have 2 components who want to access the same data. Instead of each doing an HTTP Request independantly, I wanted to keep the items in parity. When doing react, we can easily do: const [ data, setData ] = useState(undefined) which will allow us to use data in our app and setData to change the global.
I was trying to think of how this might be doable in ReactScala, and Was thinking that there could be some overlap here since you can do something like:
useState[A]( data: A ): Pair[A, A=>A] = {
val d = data
return d, x => {
d = x
return d
}
}
or similar.
I have not seen the documentation on useState in Japgolly as much as defining the property in the component state and then using the state.copy() function to update the value.
The issue which occurred is that to me, state.copy is just 1 component, and wanted to know if there was a way to genericize.
https://github.com/japgolly/scalajs-react/blob/master/doc/HOOKS.md
Under the HOOKS file linked above, the top example shows how useState is translated. I will add it below in case the file is changed or deleted:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
const [fruit, setFruit] = useState("banana");
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
<p>Your favourite fruit is a {fruit}!</p>
</div>
);
}
Compared to:
import japgolly.scalajs.react._
import japgolly.scalajs.react.vdom.html_<^._
import org.scalajs.dom.document
object Example {
val Component = ScalaFnComponent.withHooks[Unit]
.useState(0)
.useEffectBy((props, count) => Callback {
document.title = s"You clicked ${count.value} times"
})
.useState("banana")
.render((props, count, fruit) =>
<.div(
<.p(s"You clicked ${count.value} times"),
<.button(
^.onClick --> count.modState(_ + 1),
"Click me"
),
<.p(s"Your favourite fruit is a ${fruit.value}!")
)
)
}

ionic4 display Object type data in template

I am having a problem displaying data in the angular template with Ionic 4.
Here is part of the code:
here I am sending data to the template page
item: any;
constructor(public route: ActivatedRoute, items: Items) {
this.route.queryParams.subscribe(item => {
this.item = item;
});
}
here I am reading the data
<div class="item-detail" padding>
<h2>{{item.name}}</h2>
<p>{{item.about}}</p>
</div>
here is the data object value returned from the console
{
name: "Burt Bear", profilePic: "assets/img/speakers/bear.jpg", about: "Burt is a Bear."}
So the question is, how do I display these values on the HTML template with angular? This is giving me an error:
FindingItemDetailPage.html:8 ERROR TypeError: Cannot read property
'name' of undefined
Init item prop, do not let it be any. e.g
public item = {}; // or a given class/model it's up to you.
Into the constructor there is no guarantee that item is there so ensure this case and apply appropariate behavior. (again it's up to you)
e.g
constructor(public route: ActivatedRoute, items: Items) {
this.route.queryParams.subscribe(item => {
this.item = item || {} // class/model would be better;
});
}
Lastly into the template you could set *ngIf
e.g
<div class="item-detail" padding *ngIf="item.name">
to ensure that there is an item, item.name is an example, you could use a property which guarantee that there is an item.

De-structuring Mouse Move event in ReasonReact

Currently trying to pull clientX off a mouse move event in Reason React. Here is the component currently:
type state = {
count: int,
hover: bool,
mouseX: int,
mouseY: int,
};
type action =
| Hover
| MouseMove(ReactEventRe.Mouse.t);
let component = ReasonReact.reducerComponent("EventTracking");
let make = _children => {
...component,
initialState: () => { count: 0, hover: false, mouseX: 0, mouseY: 0 },
reducer: (action, state) =>
switch (action) {
| Hover => ReasonReact.Update({ ...state, hover: !state.hover })
| MouseMove(event) => ReasonReact.Update({ ...state, mouseX: state.mouseX + 1})
},
render: self =>{
let hoverString = "Hover State => " ++ string_of_bool(self.state.hover);
<div className="statistics" onMouseEnter={_event => self.send(Hover)} onMouseLeave={_event => self.send(Hover)} onMouseMove={event => self.send(MouseMove(event))}>
<p>
(ReasonReact.stringToElement(hoverString))
</p>
<p>
(ReasonReact.stringToElement(string_of_int(self.state.mouseX)))
</p>
</div>
},
};
The code I'm assuming I need to change is in my reducer's MouseMove action, mouseX needs to be updated to clientX but I can't seem to pull it off the event object without throwing errors.
Any advice would be great, I also have no idea if using these synthetic events is the right approach to tracking mouse position in ReasonReact.
You might be getting confused because ReactEventRe.Mouse.t is not a record or JS object type, but an abstract type which you manipulate with the functions in ReactEventRe.Mouse. It's pretty simple to translate though. To access the clientX property you use the clientX function. Fully qualified it would look like:
ReactEventRe.Mouse.clientX(event)
PS: You seem to be using an outdated version of ReasonReact. ReactEventRe has been replaced by ReactEvent and ReactReact.stringToElement with ReasonReact.string for example.

React onClick event is not fired when element is created in for loop

I was trying to solve this strange problem all day, but didn't managed to. This is one of the first days I am trying out React, so maybe I am missing something.
ParentComponent.cjsx
module.exports = React.createClass
getInitialState: ->
{
items: []
}
componentDidMount: ->
request.get(constants.API_ROOT + #props.source)
.end((err, res) =>
#setState({items: res.body})
)
render: ->
`
// First try: DOES NOT WORK
var items = [];
for(var i = 0; i < this.state.items.length; i++) {
var item = this.state.items[i];
items.push(<ChildItem key={item.id} id={item.id} name={item.name} src={item.image_url_640x480} />)
}
console.log(['items1', items]);
// Second try: DOES NOT WORK
var origThis = this;
var items2 = this.state.items.map(function (item) {
return (<ChildItem key={item.id} id={item.id} name={item.name} src={item.image_url_640x480} />);
}.bind(origThis), origThis);
console.log(['items2', items2]);
`
// Creating elements by hand (WORKS, but not helpful at all)
items3 = [
<ChildItem key=23 id=31 name='ddd' src='adasdas' />,
<ChildItem key=12 id=13 name='bg' src='/media/cache/de/ba/deba6d1545e209b0416b501c61fe031f.jpg' />
]
console.log(items3)
<div id="image-layer-selector" className="pure-g">{items1} {items2} {items3}</div>
ChildItem.cjsx
module.exports = React.createClass
getInitialState: ->
selected: false
handleClick: ->
console.log 'clicked'
#setState selected: true
render: ->
elemClasses = classnames('pure-u-1-2', 'selector-element', {'selected': #state.selected})
<div className={elemClasses} onClick={#handleClick}>
{#props.name} - {#props.id}
<img className="pure-img" src={constants.API_ROOT + #props.src}/>
</div>
ChildItem onClick handler is fired only when elements are set by hand. What am I missing? I tried a lot of possible ways in .cjsx, plain .jsx, .map function, plain JS for loop etc. None of these seemed to work. Console doesn't contain any errors.
Using react 13.3.
EDIT. Seems like onClick handler doesn't work only when items are set in componentDidMount using setState. Identical problem without solution is here: React - Attaching click handler to dynamic children
Finally found the problem. I haven't done any deeper investigation why this didn't work, but the problem was that in my main file I imported React as require('React'), but on other components as require('React/addons'). After importing React everywhere from react/addons everything works as expected.

ReactJS: How to access refs of child component?

I'm writing the code in CoffeeScript since I've been writing React with it.
Here is the basic structure.
{ div, input } = React.DOM
Outer = React.createClass
render: ->
div { id: 'myApp' },
Inner()
Inner = React.createClass
render: ->
input { id: 'myInput', ref: 'myInput' }
I have a toggle method on my Outer class which is triggered by pressing a shortcut. It toggles the visibility of my app.
When my app is toggled from hidden to shown, I want to focus on the input.
Now the toggle methods look more or less like this:
Outer = React.createClass
render: ->
......
hide: ->
#setState { visible: no }
show: ->
#setState { visible: yes }
$('#myInput').focus() # jQuery
# I want to do something like
# #refs.myInput.getDOMNode().focus()
# But #refs here is empty, it doesn't contain the refs in Inner
toggle: ->
if #state.visible
#hide()
else
#show()
How do I do this then?
Accessing the refs of a child breaks encapsulation since refs are not considered part of a component's API. Instead you should expose a function on Inner that can be called by a parent component, calling it focus might make sense.
Also, focus the element in componentDidUpdate to ensure rendering is complete:
{ div, input } = React.DOM
Outer = React.createClass
render: ->
div { id: 'myApp' },
Inner({ref: 'inner'})
componentDidUpdate: (prevProps, prevState) ->
# Focus if `visible` went from false to true
if (#state.visible && !prevState.visible)
#refs.inner.focus()
hide: ->
#setState { visible: no }
show: ->
#setState { visible: yes }
toggle: ->
if #state.visible
#hide()
else
#show()
Inner = React.createClass
focus: ->
#refs.myInput.getDOMNode().focus()
render: ->
input { id: 'myInput', ref: 'myInput' }
You can chain refs, so if you pull an element by ref, you can grab refs inside that element:
Defining your Outer class as
Outer = React.createClass
render: ->
div { id: 'myApp' },
Inner {ref: 'inner'}
would let you then grab the input with #refs.inner.refs.myInput.getDOMNode() to call focus on.
In this case the solution is simple, you can tell the input to autofocus, which in React focuses it when it's rendered.
Inner = React.createClass
render: ->
input { ref: 'myInput', autoFocus: true }
In general, you should pass a prop to the Inner component, and in componentDidUpdate you can do:
if #props.something
#refs.myInput.getDOMNode().focus()