KnockoutJS data-bind optionsCaption - javascript

var vm = {
WeatherId: ko.observable(),
WeatherConditions: [{
Id: '1',
Name: 'Sunny'
}, {
Id: '2',
Name: 'Rainy'
}, {
Id: '3',
Name: 'Cloudy'
}, {
Id: '4',
Name: 'Snowy'
}]
};
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<select data-bind="options: WeatherConditions,
value: WeatherId,
optionsText:'Name',
optionsCaption: 'Select today weather'">
</select>
I have this KO data bind snippet where I want to set optionsCaption to read as "Select today's weather". I wasn't able to inset the apostrophe in the middle - need help.

Escape the apostrophe with backslash \
optionsCaption: 'Select today\'s weather'">
var vm = {
WeatherId: ko.observable(),
WeatherConditions: [{
Id: '1',
Name: 'Sunny'
}, {
Id: '2',
Name: 'Rainy'
}, {
Id: '3',
Name: 'Cloudy'
}, {
Id: '4',
Name: 'Snowy'
}]
};
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<select data-bind="options: WeatherConditions,
value: WeatherId,
optionsText:'Name',
optionsCaption: 'Select today\'s weather'">
</select>

You just need to escape the ': today\'s:
var vm = {
WeatherId: ko.observable(),
WeatherConditions: [{
Id: '1',
Name: 'Sunny'
}, {
Id: '2',
Name: 'Rainy'
}, {
Id: '3',
Name: 'Cloudy'
}, {
Id: '4',
Name: 'Snowy'
}]
};
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<select data-bind="options: WeatherConditions,
value: WeatherId,
optionsText:'Name',
optionsCaption: 'Select today\'s weather'">
</select>
This isn't a KnockoutJS thing, it's a basic JavaScript thing. To put a ' in a '-quoted string, you use an escape: today\'s.
Remember, the content of the data-bind attribute is an JavaScript object initializer without the { and }, whose contents are evaluated within a series of with blocks to provide context. (Literally. Knockout builds the text of a function to do that, using as many with blocks as it needs for the nesting level, and with a return {" + theDataBindAttributeText}; at the end, then uses new Function to build a function from that, and calls it to get the bindings.)

Related

I'm trying to filter items from array by accessing a nested property & checking if it property value contains a certain string

I'm trying to filter an array of objects by the summary nested property, if it includes the word Save in the summary prop value string. This is the array:
const issues = [{
id: '1',
key: 'CLS-1',
fields: {
summary: 'Save princess',
assignee: 'Mario',
}
},
{
id: '2',
key: 'CLS-2',
fields: {
summary: 'Save Mario',
assignee: 'Luigi',
}
},
{
id: '3',
key: 'CLS-3',
fields: {
summary: 'Kidnap princess',
assignee: 'Bowser',
}
},
{
id: '4',
key: 'CLS-3',
fields: {
summary: 'Get kidnap!',
assignee: 'Peach',
}
},
]
I have tried this one-liner:
const getItemsBySummary = items.filter(item => item.fields.includes('Save'));
But I get the error item.fields.includes is not a function. I'm guessing because fieldsis anobjectinstead of anarrayso it cannot run the methodincludes()`. However, I tried like so
const getItemsBySummary = items.filter(item => [item.fields].includes('Save'));
But I get an empty array. What am I doing wrong?
well since fields is an object , and you want to filtre according to the proptery summary , you should use this instead :/
const getItemsBySummary = items.filter(item => item.fields.summary.includes('Save'));
You need item.fields.summary to access the required field.
const items = [{
id: '1',
key: 'CLS-1',
fields: {
summary: 'Save princess',
assignee: 'Mario',
}
},
{
id: '2',
key: 'CLS-2',
fields: {
summary: 'Save Mario',
assignee: 'Luigi',
}
},
{
id: '3',
key: 'CLS-3',
fields: {
summary: 'Kidnap princess',
assignee: 'Bowser',
}
},
{
id: '4',
key: 'CLS-3',
fields: {
summary: 'Get kidnap!',
assignee: 'Peach',
}
},
]
const res = items.filter(item => item.fields.summary.includes('Save'));
console.log(res);

How to have the whole object act as optionValue in a SelctInput in react-admin?

Consider the following simple example for a SelectInput field with static choices in react-admin:
<SelectInput source="category" choices={[
{ id: '1', name: 'Programming' },
{ id: '2', name: 'Lifestyle' },
{ id: '3', name: 'Photography' },
]} />
When the user selects a choice, the category field is filled with the id as expected.
I'd like to have the category field filled with the whole object, like { id: '2', name: 'Lifestyle' } instead of just '2'. The API I'm using unfortunately requires that.
I tried with
const myWeirdChoices = [{ id: { id: '1', name: 'Programming' }, name: 'Programming' },
{ id: { id: '2', name: 'Lifestyle' }, name: 'Lifestyle' },
{ id: { id: '3', name: 'Photography' }, name: 'Photography' }];
<SelectInput source="category" choices={myWeirdChoices } />
but now the SelectInput is empty even if the field already contained a proper value.
Is there a prop on SelectInput which tells the component to use the whole thing as an OptionValue instead of just the id, so I can use the more elegant first code block?
Unfortunately, you cannot do this. the OptionValue argument is only allowed to be a property name of a value field, even if it is a nested one, its value must not be an object.
And beware, if you set this to anything other than 'id' when the ReferenceInput, you will get a dataProvider get call to that, as if it was the id of the resource. That probably isn't what you want and that behavior is arguably a bug.
As of React-Admin v3.13 this is possible using parse and format.
const choices = [
{ id: '1', name: 'Programming' },
{ id: '2', name: 'Lifestyle' },
{ id: '3', name: 'Photography' },
];
<SelectInput
source="category"
choices={choices}
format={(c) => c.name}
parse={(name) => choices.find((c) => c.name === name)}
/>
format makes sure the form options in the html are just the name strings. parse translates the selected option into the format you db needs.

Assign array values to an item in object - Javascript/React

I have an object with few items and I want to update the values of one property from array.
Object :
structure = [
{
id: 'name',
label: 'Name',
filterType: 'text',
filterOn: 'contains'
},
{
id: 'address',
label: 'Address',
filterType: 'text',
filterOn: 'contains'
},
{
id: 'phone',
label: 'Phone',
filterType: 'select',
filterOn: 'contains',
options: [{ label: 'abc', value: 'abc' },
{ label: 'xyz', value: 'xyz' },
{ label: 'mno', value: 'mno' }]
}
];
if the id is phone then I want to get the values from the array and assign it to the options instead of hard coding it.
In this object of id phone:
options: [{ label: 'abc', value: 'abc' },
{ label: 'xyz', value: 'xyz' },
{ label: 'mno', value: 'mno' }]
}
];
array is coming from
this.props.phoneList
label and values will be this.props.phoneList[i].name
how to loop over this and get the latest values from the array
This should keep the order of the array intact also:
const newStructure = structure.map(item => {
const isPhone = item.id === “phone”
return {
...item,
options: isPhone ? this.props.phoneList : (item.options || undefined)
}
}

Chain + filter + value returning value is not a function?

I've following array of objects. Each object in the array contain user information.
var usersAll = [
{ id: '1', name: 'User 1', selected: true },
{ id: '2', name: 'User 2' },
{ id: '3', name: 'User 3' },
{ id: '4', name: 'User 4' }];
I want to extract the users for whom, selected is set to true.
This is the code I'm using
var selectedUsers = _(usersAll)
.filter(function(u) {
return u.selected
})
.map(function(u) {
return u.name
}
.value()
But for some reason it returns this:
TypeError: _(...).filter(...).value is not a function
What am I doing wrong?
Use _.filter with _.pluck
Filter the array to keep users whose selected value is true.
Use Pluck to get the array of values of the name.
var usersAll = [{id: '1', name: 'User 1', selected: true},
{ id: '2', name: 'User 2'},
{ id: '3', name: 'User 3'},
{ id: '4', name: 'User 4', selected: true}
];
var selectedUserNames = _.pluck(_.filter(usersAll, 'selected'), 'name');
console.log(selectedUserNames);
document.write(selectedUserNames);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
If you don't want to use any library, this can be done in JavaScript using Array#filter and Array#map.
var usersAll = [{id: '1', name: 'User 1', selected: true},
{ id: '2', name: 'User 2'},
{ id: '3', name: 'User 3'},
{ id: '4', name: 'User 4', selected: true}
];
var selectedUserNames = usersAll.filter(function(e) {
return e.selected;
}).map(function(e) {
return e.name;
});
console.log(selectedUserNames);
document.write(selectedUserNames);
Using EcmaScript 6/ES15 arrow function, it can be done in a single line
usersAll.filter(e => e.selected).map(e => e.name);
For those using 4.0.1 and above, in case you chain with each(), it seems there could an issue. Check this https://github.com/lodash/lodash/issues/1879
The issue may be something like Uncaught TypeError: _(...).filter(...).each(...).value is not a function
The solution would be to explicitly call the chain method
_.chain(usersAll) // instead of _(usersAll)
... // other chaining
.each(function(u) {
...
}
.value()

How to Multiple Default Select Option in AngularJS?

I'd like to have multiple default selected option in AngularJs.
In my controller code:
$scope.selectedFvs = ['fvid9', 'fvid2'];
$scope.fields = [{
id: 'fid1',
name: 'f name 1',
fieldValues: [{
id: 'fvid1',
name: 'fv name 1',
}, {
id: 'fvid2',
name: 'fv name 2'
}]
}, {
id: 'fid2',
name: 'f name 2',
fieldValues: [{
id: 'fvid3',
name: 'fv name 3',
}, {
id: 'fvid4',
name: 'fv name 4'
}, {
id: 'fvid5',
name: 'fv name 5',
}, {
id: 'fvid6',
name: 'fv name 6'
}]
}, {
id: 'fid3',
name: 'f name 3',
fieldValues: [{
id: 'fvid7',
name: 'fv name 7',
}, {
id: 'fvid8',
name: 'fv name 8'
}, {
id: 'fvid9',
name: 'fv name 9',
}]
}];
In HTML code:
<div ng-repeat="field in fields">
<label>{{::field.name}}</label>
<select ng-init="fields[field.id] = selectedFvs[1]" ng-model="fields[field.id]">
<option value="select-all">Select All</option>
<option ng-repeat="fieldValue in field.fieldValues" value="{{::fieldValue.id}}">{{fieldValue.name}}</option>
</select>
</div>
This renders with 'fv name 5' as default selected field value because in the HTML code, the select tag, the ng-init is set to the second index of selectedFvs:
However, this is not what I want. What I really want is the 3 selects have the default value of selectedFvs. It would look like this if it works,
Here is the Plunker link to this code.
Use $index as follows
<div ng-repeat="field in fields">
<label>{{::field.name}}</label>
<select ng-init="fields[field.id] = (selectedFvs|findselected: field.fieldValues)" ng-model="fields[field.id]">
<option value="select-all">Select All</option>
<option ng-repeat="fieldValue in field.fieldValues" value="{{::fieldValue.id}}">{{fieldValue.name}}</option>
</select>
</div>
Uae this filter as well
app.filter("findselected", function() { // register new filter
return function(inputs, fields) { // filter arguments
var selected = '';
angular.forEach(inputs, function(val1){
angular.forEach(fields, function(val2){
if(val1 === val2.id){
selected = val1;
}
})
});
return selected;
};
});
See this Plunker
Use selectedFvs[$index] instead of selectedFvs[1]

Categories

Resources