Why tab space causes error in coffee script - reactjs

I am learning react with rails from here. On following tutorial I canme to this error
ExecJS::RuntimeError in Records#index
SyntaxError: [stdin]:41:13: cannot have an implicit value in an implicit object
And then from little bit research on google, I came to know error is coming because of tab space.
Check this react js code:
#RecordForm = React.createClass
getInitialState: ->
title: ''
date: ''
amount: ''
render: ->
React.Dom.form
className: 'form-inline'
React.DOM.div
className: 'form-group'
React.DOM.input
type: 'text'
className: 'form-control'
placeholder: 'Date'
name: 'date'
value: #state.date
onChange: #handleChange
React.DOM.div
className: 'form-group'
React.DOM.input
type: 'text'
className: 'form-control'
placeholder: 'Title'
name: 'title'
value: #state.title
onChange: #handleChange
React.DOM.div
className: 'form-group'
React.DOM.input
type: 'number'
className: 'form-control'
placeholder: 'Amount'
name: 'amount'
value: #state.amount
onChange: #handleChange
React.DOM.button
type: 'submit'
className: 'btn btn-primary'
disabled: !#valid()
'Create record'
handleChange: (e) ->
name = e.target.name
#setState "#{ name }": e.target.value
valid: ->
#state.title && #state.date && #state.amount
handleSubmit: (e) ->
e.preventDefault()
$.post '', { record: #state }, (data) =>
#props.handleNewRecord data
#setState #getInitialState()
, 'JSON'
render: ->
React.DOM.form
className: 'form-inline'
onSubmit: #handleSubmit
Removing the spaces before 'Create record' from the above script will solve the problem. You can check it by this utility(link)

You should declare object in 2 ways and your compiler can't decide which of them you use.
The best way to avoid errors like yours is to choice one of the methods within each declaration.
# First way
obj =
a : 1
b : 2
# First way (compact)
obj = a : 1, b : 2
# Second way
# vars and props with same names (compact)
a = 1; b = 2
obj = {
a
b
}
# Second way (compact)
a = 1; b = 2
obj = {a, b}
You can also use React JSX support for Coffeescript
update:
Lets look closer to you code.
You can send two arguments like that.
React.DOM.button
type : 'submit'
className : 'btn btn-primary'
disabled : !#valid()
, 'Create record'
Or like that.
The combination of entering object and not object compiles into two arguments.
type : 'submit'
className : 'btn btn-primary'
disabled : !#valid()
'Create record'
And what you do in your code Compiler try to send Object {'Create record' : 'Create record'} as argument into result of call !#valid().
React.DOM.button
type: 'submit'
className: 'btn btn-primary'
disabled: !#valid()
'Create record'

Related

update one element of array inside object and return immutable state - redux [duplicate]

In React's this.state I have a property called formErrors containing the following dynamic array of objects.
[
{fieldName: 'title', valid: false},
{fieldName: 'description', valid: true},
{fieldName: 'cityId', valid: false},
{fieldName: 'hostDescription', valid: false},
]
Let's say I would need to update state's object having the fieldName cityId to the valid value of true.
What's the easiest or most common way to solve this?
I'm OK to use any of the libraries immutability-helper, immutable-js etc or ES6. I've tried and googled this for over 4 hours, and still cannot wrap my head around it. Would be extremely grateful for some help.
You can use map to iterate the data and check for the fieldName, if fieldName is cityId then you need to change the value and return a new object otherwise just return the same object.
Write it like this:
var data = [
{fieldName: 'title', valid: false},
{fieldName: 'description', valid: true},
{fieldName: 'cityId', valid: false},
{fieldName: 'hostDescription', valid: false},
]
var newData = data.map(el => {
if(el.fieldName == 'cityId')
return Object.assign({}, el, {valid:true})
return el
});
this.setState({ data: newData });
Here is a sample example - ES6
The left is the code, and the right is the output
Here is the code below
const data = [
{ fieldName: 'title', valid: false },
{ fieldName: 'description', valid: true },
{ fieldName: 'cityId', valid: false }, // old data
{ fieldName: 'hostDescription', valid: false },
]
const newData = data.map(obj => {
if(obj.fieldName === 'cityId') // check if fieldName equals to cityId
return {
...obj,
valid: true,
description: 'You can also add more values here' // Example of data extra fields
}
return obj
});
const result = { data: newData };
console.log(result);
this.setState({ data: newData });
Hope this helps,
Happy Coding!
How about immutability-helper? Works very well. You're looking for the $merge command I think.
#FellowStranger: I have one (and only one) section of my redux state that is an array of objects. I use the index in the reducer to update the correct entry:
case EMIT_DATA_TYPE_SELECT_CHANGE:
return state.map( (sigmap, index) => {
if ( index !== action.payload.index ) {
return sigmap;
} else {
return update(sigmap, {$merge: {
data_type: action.payload.value
}})
}
})
Frankly, this is kind of greasy, and I intend to change that part of my state object, but it does work... It doesn't sound like you're using redux but the tactic should be similar.
Instead of storing your values in an array, I strongly suggest using an object instead so you can easily specify which element you want to update. In the example below the key is the fieldName but it can be any unique identifier:
var fields = {
title: {
valid: false
},
description: {
valid: true
}
}
then you can use immutability-helper's update function:
var newFields = update(fields, {title: {valid: {$set: true}}})

Select certain items from array of objects to create new array in Typescript?

I would like to create an array of strings out of a separate array object.
export interface box{
image: string,
link: string,
button_name: string,
info: string,
description: string
}
export const BOX: box[] = [
{image: 'image here', link: 'google.com',
button_name: 'name', info: 'some information', description: "a description"
},
{image: 'image here again', link: 'another google.com',
button_name: 'another name', info: 'some more information', description: "another description"
},
]
Essentially I would like to create a new array out of this existing information, but it would just be an array of info. I am unsure how to implement this in typescript. I have tried using the ForEach function like so:
infos: string[] = BOX.forEach(element => element.info);
but this will return me an error saying that
Type 'void' is not assignable to type 'string[]'
How can I create an array of strings that consist of just the info fields of my existing array?
You can use the map function on the BOX-array. It will return a new array with what you put in the arrow function. If you only want the element's info, you can do this
infos: string[] = BOX.map(element => element.info);
The above has an implicit return statement, and is the shorthand for the same function below.
infos: string[] = BOX.map(element => {
return element.info;
});
Here are some more information about the topic
const infos = BOX.map(element => element.info);
infos: string[] = BOX.forEach(element => element.info);
Array.prototype.forEach returns undefined from the definition.
It only executes the provided function once for each array element.
So in your case, you need to use Array.prototype.map function to map info param for each element.
const infos = BOX.map(el => el.info);

Access data from arr of objects using props passed to children - error

Using props passed down to functional component to access data from an array of objects. Getting the following result when the code is running.
I have tried assigning props.id to a variable and using that in its place but get the same error, why is this happening and how can I work around it/fix it?
Object:
const items = [
{
url: 'sample url 1',
desc: 'Description 1'
},
{
url: 'sample url 2',
desc: 'Description 2'
}
Attempt to log the data:
console.log(items[props.id].url);
Output:
TypeError: Cannot read property 'url' of undefined
Id sounds a bit misleading here. What you are trying to do is to assign the index of an element to the variable props.id. The index can be (as you can read in the comment by Felix) be 0 or 1 since your array has two elements in it.
There are two options here:
Stick with using index
Call it props.index and make sure that props.index < items.length at all times to avoid Type and OutOfBounds errors.
Actually creating an id
const items = [
{
id: 1,
url: 'sample url 1',
desc: 'Description 1'
},
{
id: 2,
url: 'sample url 2',
desc: 'Description 2'
}
and using props.id to filter for the id as follows:
const item = items.find(i => i.id === props.id);
if(!item) {
console.log('this id does not exist!', id);
}
// now you can use the item

Ionic 2 / 3: Number Input from Alert

I'm using Ionic 3.x on macOS.
I have the following issue:
I have an array containing a number and an array of names.
table: { number: number, names: string[] } = {
number: 0,
names: ['']
};
I want to set the number of the array using an input for the user. I stumbled upon the AlertController.
I have written the following function thing to add a number:
addTable(){
let prompt = this.alertCtrl.create({
title: 'Add Table',
subTitle: 'Enter the table number',
inputs: [{
name: 'tableNumber',
placeholder: 'Number',
type: 'number'
}],
buttons: [
{
text: 'Cancel'
},
{
text: 'Add',
handler: data => {
//this.tables.push(data);
this.table.number = data;
}
}
]
});
prompt.present();
}
But this always sets table.number to object [object]. If I write it as this.table.number = +data; it has the value NaN. The push version also doesn't work.
How do I set table.number to a number that the user put in?
The name of the input
name: 'tableNumber'
gets added as a property name to the resulting object. You can access it like this:
handler: data => {
this.table.number = data.tableNumber;
}

Need to find the way to slice this array to show only n customers

So , i basically want to show only 5 customer per page, i'll later add a pagination bar but at the moment i want to show only 5 customer, i have tried to slice after the map function, but im kinda new to react and redux and im not sure if that's the way.
const Setting = ({
itemFromPage,
BBDDCustomer
}) => {
console.log({BBDDCustomer});
const renderRows = BBDDCustomer.data.map((customer, customerIndex) => { //how to slice this array
return (
<tr key={customerIndex}>
<td>{BBDDCustomer.data[customerIndex].name}</td>
<td>{BBDDCustomer.data[customerIndex].address}</td>
<td>{BBDDCustomer.data[customerIndex].postalCode}</td>
<td>{BBDDCustomer.data[customerIndex].city}</td>
<td>{BBDDCustomer.data[customerIndex].country}</td>
<td>{BBDDCustomer.data[customerIndex].telephone}</td>
<td>{BBDDCustomer.data[customerIndex].email}</td>
<td><input type="checkbox" id="customerIndex" value="mod"/></td>
<td><input type="checkbox" id="customerIndex" value="Del"/></td>
</tr>
);
});
return (
<div>
<Table>
</div>
);
};
This is the format file where the customer are:
const BBDDCustomer = {
ui_labels: {
name: 'Name',
address: 'address',
postalCode: 'Postal Code',
city: 'City',
country: 'Country',
telephone: 'Telephone',
email: 'Email',
modified: 'Modified',
delete: 'Delete'
},
data: [
{
name: 'n1',
address: 'a1',
postalCode: 'PC 1',
city: 'c 1',
country: 'cou 1',
telephone: 'tel 1',
email: 'em 1'
}
}
It is better to get a sub-array and render it than render the whole array and get a sub-array.
There is a standard Javascript slice(from, count?) method to get a part of array, first parameter tells the index to start with, second optional parameter is the number of elements to be included
You would use it like so:
const renderRows = BBDDCustomer.data.slice(0, 5).map((customer, customerIndex) => { ... };
It would return first 5 elements which you would map with your array function.

Resources