What is the pattern to bind an array of data to an element, and have that element "auto update" when any part of the array changes?
Say in a script I bound an array to app.game.gameData = [] and then bound that array to an element
<template is="dom-bind" id="app">
...
<game-mat screens={{game.gameData}}></game-mat>
I have my game-mat element set up with dom-repeat, it passes values to sub-elements, etc.
But I want game-mat to update when I add a new item to game.gameData. Show the new row, etc. And, I want the sub-elements to change because of the binding set up, like if I change game.gameData[3].value = 50, I want that to be reflected in that sub element.
From what I can tell now, the only array that renders is the initial one created.
I want to manipulate this data and have it be reflected in that list of elements. Any good way to do that?
(I'd gladly change my existing patterns around, just don't know of a way to go about this right now...)
Update Your array with push, pop, splice, shift, unshift methods.
for example push object to this.employees:
this.push('employees', { first: 'Jack', last: 'Aubrey' });
or set sub-element
this.set('employees.0.manager.type', 'engineer');
for more information you can read the polymer guide for arrays in
https://www.polymer-project.org/1.0/docs/devguide/templates.html
Related
console.log(holder);
console.log(index);
console.log(holder);
setWholeData(wholeData.filter((el, i) => i !== index));
console.log(holder);
For the above code, I want to remove one element with index = 'index' in wholeData which is a state setup using useState and initialize with []. In my test case, before this part of code, wholedata should have two elements and this part of code should remove one of its elements. I assign the updated/New array to holder and want to assign it to wholedata using 'setWholeData()".
But the problem is that if I do
setWholeData(holder). Then the holder will contain two elements, which means that the filter function did not work somehow. If I do
setWholeData(wholeData.filter((el, i) => i !== index));
The value of holder is what I expected, but 'wholedata' is not updated correctly still. The element is not removed. Seems like the filter in the
setWholeData(...) is not working.
If anyone could give a little hand, it would be so appreciated. Sorry for the confusing description, if any clarification is needed, please feel free to message.
Filter returns an array where the result of the callback is 'true'.
If you want to remove an element by its index you can use a combination of findIndex and splice to find the index of the element you want to remove and splice to execute the removal of that element.
I have an oberservable, which is an array:
items$: Observable<CarClassification[]>;
And I am trying to translate/convert this into a new Observable of an array of SelectItems for a dropdown box.
get SelectItems(): Observable<SelectItem[]> { ...
Which I can then set as the datasource for the dropdown box, and, if any item in items$ is modified, deleted or a new one added, the array of SelectItems changes as wel. The issue I am having is that I have dozens of these arrays (criteria for a larger object) that need to be defined in this way. Everything I have tried to date, if it works, is just too slow (subscribing to the observable and pushing to a new array) and I am looking for a more seamless way.
I'm new to RxJS, and I have tried a few different things, but none seem to work. I've search as much StackOverflow as I think I ever have.
CarClassification has two properties, Id and Name that I want to make the value and label of the SelectItem.
I know I can map the observable to an array:
items$.map((items) => { ...
But how to then properly iterate over each item in items, and return a new SelectItem for each has been eluding me.
If you have an Observable that emits arrays you can always unpack it with concatAll() and then pack it again like for example this:
Observable.of([{...}, {...}, {...}])
.concatAll() // unpack
// will emit each {...} as a single value
.toArray() // pack
But you don't need to use Rx to transform the array at all:
items$.map((items: CarClassification[]) => {
return items.map((item: CarClassification) => new SelectItem(...));
});
Now you have Observable<SelectItem[]>.
I not sure how to solve this issue. I am sure someone will know this very quickly.
I have an array of objects and modifying a property. I have a firebase listener 'child_changed'. When firebase is updated need to update the array. Here is the code below.
dbRefList.on('child_changed', function(snap) {
var len = this.grocerylist.length;
for(var i=len; i--;) {
if(this.grocerylist[i].key === snap.key) {
this.set(['grocerylist', i, 'selected'], snap.val().selected);
}
}
this.notifyPath('grocerylist', this.grocerylist.slice());
}.bind(this));
When the array is modified I want the template repeat-dom to trigger. I know this.set will not trigger array mutation sub properties but again I am not sure how to solve this. I done research and tried so many solutions.
I can force a render on the template dom-repeat but I would prefer the data binding way.
So this code (just the this.set you have in there now) should cause the value of grocerylist.i.selected to update inside the dom-repeat (assuming it's bound in there so it's actually showing up).
What behavior are you seeing? Are you trying to filter or sort the list based on the selected value? In that case, you might need to add observe="selected" on the dom-repeat.
(Also—have you confirmed that the child-changed callback is being called with the this value you expect—the element—rather than window or something else?)
You should be able to force a refresh by doing this.grocerylist = this.grocerylist.slice() or this.set('grocerylist', this.grocerylist.slice()); ... notifyPath doesn't work here because notifyPath doesn't change the value, it notifies the element about a prior change (the second argument is effectively ignored).
I want to use angularJS Dropdown Multiselect from this link.
The problem is that selected items stored in this format(as array of objects):
[{"id": 3},{"id": 2},{"id": 1}]
While I need to store selected values in this format(as array on int's):
[3,2,1]
I tried to figure out how I have to change the code in directive to make
the change above but I did not succeed the directive didn't work properly after I made changes.
Any idea how can I store only array of id's not array of objects?
I am learning knockout and was trying to build a page that will build a list of selectable users.
JSFiddle: http://jsfiddle.net/Just/XtzJk/3/ (I am unable to get the data assignment right).
The data assignment is working in my page as I make a call to Controller, like below and it binds to the controls as expected
$.getJSON("/Wizard/GetUsers",function(allData){
var mappedUsers = $.map(allData.AllUsers, function(item){return new User(item)});
self.AllUsers(mappedUsers);
if(allData.SelectedUsers != null){
var mappedSelectedUsers = $.map(allData.SelectedUsers, function(item){return new User(item)});
self.SelectedUsers(mappedSelectedUsers);}
});
Problems:
a.) What's wrong with the JSFiddle I wrote? Got it working.
b.) In my code I am able to get the function for selected checkbox invoked but I am unable to get the value stored in the "User" parameter that I receive in the function. In Chrome JS console I can see the user object has the right value stored, I just am unable to retrieve it. Got this by doing ko.toJS().
Thanks.
EDIT:
Ok, I got my JSFiddle working, I had to select Knockout.js in the framework. The updated fiddle: http://jsfiddle.net/Just/XtzJk/5/
Also, for getting the selected checkboxe's value I did
ko.toJS(user).userName
But I think I'll take the approach of selecting values from a list and then on click move them to another "Selected" list and remove the values from the previous ones. Got this idea from this post: KnockoutJS: How to add one observableArray to another?
OK, I think I've got the solution you need...
I started by setting up an observable array of selectedUserNames, and I applied this to the <li> elements like this:
<input type="checkbox"
name="checkedUser"
data-bind="value: userName, checked:$root.selectedUserNames" />
[Note: it's important to declare the value before declaring the checked binding, which threw me for a bit… ya learn something new every day!]
Why bind an array of userName values to the checked binding? Well, when an array is passed to the checked binding, KO will compare the value of each checkbox to the values in the checked array and check any checkbox where its value is in that array. (Probably explained better in the KO documentation)
Then, while I left the observableArray for SelectedUsers, I set up a manual subscription to populate it, like so:
self.selectedUserNames.subscribe(function(newValue) {
var newSelectedUserNames = newValue;
var newSelectedUsers = [];
ko.utils.arrayForEach(newSelectedUserNames, function(userName) {
var selectedUser = ko.utils.arrayFirst(self.AllUsers(), function(user) {
return (user.userName() === userName);
});
newSelectedUsers.push(selectedUser);
});
self.SelectedUsers(newSelectedUsers);
});
[I had originally tried to set up a dependent observable (ko.computed) for selectedUserNames with functions for both read and write, but the checkbox wasn't having it.]
This subscription function examines the new selectedUserNames array, looks up the user from AllUsers whose userName matches a value in that selectedUserNames array, and pushes matching User objects to the SelectedUsers array… well, actually it pushes each matching User to a temp array and then that temp array is assigned to SelectedUsers, but the goal is met. The SelectedUsers array will now always contain what we want it to contain.
Oh, I almost forgot… here's the fiddle I created, so you've got the full solution: http://jsfiddle.net/jimmym715/G2hxP/
Hope this helps, but let me know if you have any questions