extracting information from array using knockout - arrays

I currently have an array being passed into my function and i wanted to pull out the information from the array so i can display it on the page.
This is what the array looks like:
EducationalClasses:[object, object]
first object contains:
classId: "324342",
className: "English 101"
second object contains:
classId: "231243",
className: "Reading"
when i do educationalClasses[0] i get the results as in first object. I wanted to create some sort of loop so that in my view page when i have:
<!-- ko foreach: educationalClasses -->
<div data-bind="text: className></div>
<!--/ko-->
i would get English 101 and Reading displayed
This is what i have for my viewModel:
viewModel = function(educationalClasses){
....
self.className= ko.observable(educationalClasses.className); // what i want
}
How can i do this properly and so that all the items in the array are displayed without me having to use educationalClasses[0].className...educationalClasses[1].className

Technically, you don't need any observables for what you're doing here. You just need your viewmodel to have a member named educationalClasses that is an array (or observableArray). You can just wrap your raw data in an object, label it, and it goes.
If you want to change the array and have the view show the updates, you'll want an observableArray. If you want changes to the individual data items to show, you'd want them to be observables as well.
rawData = [{
classId: "324342",
className: "English 101"
}, {
classId: "231243",
className: "Reading"
}];
viewModel = function(educationalClasses) {
return {
educationalClasses: educationalClasses
};
};
ko.applyBindings(viewModel(rawData));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<!-- ko foreach: educationalClasses -->
<div data-bind="text: className"></div>
<!--/ko-->

Related

Angular ng-repeat rendering issue for small lidt

I have the 2 of objects below:
$scope.MyObj_1={
Id:"1",
Title:"Title1",
Items:[
{
Id:"1",
Comment:"Simple comment 1",
}
]
};
$scope.MyObj_2={
Id:"2",
Title:"Title1",
Items:[
{
Id:"2",
Comment:"Simple comment 2",
},
{
Id:"3",
Comment:"Simple comment 3",
},
{
Id:"4",
Comment:"Simple comment 4",
}
]
};
And I have this html template (just to simplify):
<ul>
<li ng-repeat="note in MyObj.Items" >{{item.Comment}}</li>
</ul>
When I set MyObj with MyObj_1 value and then I set MyObj with MyObj_2 I am getting rendering problem related to the slowness of ng-repeat. In fact ng-repeat starts by adding items of MyObj_2 and then removes the item related to MyObj_1.
I tried ng-cloak and $timeout but the behavior still the same.
I am wondering why ng-repeat did not remove old element first and then push new elements.
Angular.copy makes clone of object from source to destination.It deletes all objects from destination object and then copy properties from source.
Angular.merge appends the source object to destination.If destination object already has elements, it will remain there and new properties from source object will add to destination object.
The behavior is expected if you set the $scope.MyObj_2 = $scope.MyObj_1;
Then they will point to the same reference in memory.
What you need to use is angular.copy() which creates a deep copy of source like this
$scope.MyObj_2 = angular.copy($scope.MyObj_1);
Also, in the repeat you have a typeo, should be
<ul>
<li ng-repeat="note in MyObj.Items" >{{note.Comment}}</li>
</ul>

Create list of items of a single item at once

Angular task 1.5.x:
I have object like this:
{
id: 1,
name: "a",
items: [
{"holiday": "false", "day": "monday"},
{"holiday": "true", "day": "tuesday"...}
]
}
I want a new object to be created in the above way with click of a single button. Note I dont want to add each item separately, all at once. Means, for a single object with name "a", I want to add all items for all days at once.
I can make it work but I want to know the correct way.
ultimately we should be able to create a javascript object in the above format(without id)(I think this format is correct) and send it to server so it will work. But how to add html/angular code so I will get an object that way.
Please let me know for more info.
When using ng-model you do not have to fully define your object in order to have it constructed. E.g.:
Controller
$scope.object= {
items: []
};
var n = 7;
for (var i = 0; i < n; i++)
$scope.object.items({});
HTML
<input type="text" ng-model="object.name"/>
<div ng-repeat="currObj in object.items">
<input type="text" ng-model="currObj.holiday" />
<input type="text" ng-model="currObj.day" />
</div>
The general structure must be defined beforehand, but you do not have to initialize all the properties. They will receive values when binding is triggered (view -> model).
You can do like this :
Create a button in your view and use ng-click directive to capture on click event.
Html:
<button ng-click="createCopy()"></button>
Use angular.copy to create a deep copy of the source object.
This is what angular.copy does as explained in the docs :
Creates a deep copy of source, which should be an object or an array.
If no destination is supplied, a copy of the object or array is
created. If a destination is provided, all of its elements (for
arrays) or properties (for objects) are deleted and then all
elements/properties from the source are copied to it. If source is not
an object or array (inc. null and undefined), source is returned. If
source is identical to destination an exception will be thrown.
Controller:
$scope.mainObject = { id: 1, name: "a", items: [{"holiday": "false", "day": "monday"}, {"holiday": "true", "day": "tuesday"...}] };
$scope.createCopy = function (){
$scope.copyObject = angular.copy($scope.mainObject);
}

Access selectedItems of an <iron-list> on change

Having trouble understanding how to access the selectedItems property of an iron-list. When bound to a property of the parent, I can output it's contents using a template, but an observer or computed binding does not fire when it changes and I can't seem to output it's contents.
If anyone could point out what I'm doing wrong, how I can read the selectedItems for logic, or how I can observe changes to an iron-list selectedItems property, I would greatly appreciate the know how. Thanks.
Below is some example code to show how I am using the selectedItems property of iron-list:
<dom-module id="example-component">
<template>
<iron-list
id="dataList"
items="[[data]]"
as="item"
multi-selection
selection-enabled
selected-items="{{selectedItems}}">
<template>
<span>[[item.data]]</span>
</template>
</iron-list>
<template is="dom-repeat" items="[[selectedItems]]" index-as="index">
<div>[[item.data]]</div> <!-- this displays any selected item -->
</template>
</template>
<script>
Polymer({
is: 'example-component',
properties: {
data: {
type: Array,
value: [
{
'data': "item 0"
},
{
'data': "item 1"
}
]
},
selectedItems:
{
type: Object,
observer: '_selectedItemsChanged'
}
},
_selectedItemsChanged: function(){
console.log(this.selectedItems); //this neither runs nor outputs anything when an item is selected
}
});
</script>
From the docs:
Finally, to observe mutations to arrays (changes resulting from calls to push, pop, shift, unshift, and splice, generally referred to as “splices”), specify a path to an array followed by .splices as an argument to the observer function.
Therefore, remove the selectedItems property and add a manual observer like so:
observers: [
'_selectedItemsChanged(selectedItems.splices)'
],

List items by type in AngularJs using ng-repeat

I have some items, lets say they are Cars. I am using ng repeat to list them.
Cars also have tires. Let's say I want to list all of the tire options, but there are a several different types of tires, so we want to separate them by their type {summer, road, racing, etc....):
<div class="col-md-4" ng-repeat="individualCar in allCars" ng-show="CarTypeFilter[individualCar.type]">
<div class="">
{{individualCar.name}}
</div>
<ul>
<!-- This is the list of all one type of tires -->
<li class="TireType1" ng-repeat="tire in individualCar.tires" ng-show="CarTireFilter[tire.type]">
{{tire.name}}
</li>
<!-- This is another list of all another type of tires -->
<li class="TireType2" ng-repeat="tire in individualCar.tires" ng-show="CarTireFilter[tire.type]">
{{tire.name}}
</li>
</ul>
</div>
This isn't quite working, since there isn't a separate list of tire types per Car on the Controller $scope, and Im not sure if I need to build one to reference. How do I filter or list the types of tires separately using ng-repeat?
I plan on styling them differently, hence the distinction needed.
Example JSON:
{
"jokes":[
{
"id:":1,
"name":"Tesla",
"type":"CAR",
"Tires":[
{
"id":1,
"type": "summer",
"name":"Goodyear"
},
{
"id":2,
"type": "summer",
"name":"Kuhmo"
},
{
"id":3,
"type": "winter",
"name":"Perelli"
},
{
"id":4,
"type": "racing",
"name":"Cooper"
}
]
},
{...}
]
}
In the controller, I have an associative array that stores the different types {summer, racing, etc) as the key, and a boolean value, so that when they want to see each option via a checkbox, the items show in the ng-repeat:
$scope.CarTireFilter = {"summer":true, "racing":false, ... };
If you are wanting to only show items in the list by some specific atrribute then a filter is what you need. See the docs for Filter & OrderBy.
Do not us ng-show rather use this:
div class="col-md-4" ng-repeat="individualCar in allCars|
filter: SET CONDITIONS HERE |
orderBy: SET CONDITIONS HERE">
The other thing I would like suggest is that if you are going to be adding styling based on the various types. You might want to look into doing this in a more angular way using ng-style. Look at the docs ng-style. This approach would allow you add the needed styles based on type and not necessarily need to have separate li tags with different classes. you should try and let angular handle this.

Path notification for changes to an object within an array?

We have a large model object that is owned and managed outside of polymer. We want to expose this model to polymer elements through a proxy element that exposes computed parts of it.
For example, the model may have:
{
blocks: {
...
properties: [
{ ... }, // prop0
{ ... }, // prop1
]
},
}
We are using recursive object observers and array observers to monitor changes to the model and notify polymer appropriately (either using .notifyPath(path, ...) for object changes and ._notifySplice(...) for array changes). However, there doesn't seem to be a good way for us to notify of changes to an object within an array, e.g. prop0 changed in the example above.
Is there? What should the path be?
Here's an example using binding to show an updated Polymer property nested inside an object and array:
code:
<div>
<h1>[[blocks.properties[0]]]</h1>
<p>this updated property should read: Apple</p>
</div>
script:
Polymer({
is: "my-page",
properties: {
blocks: {
type: Object,
value: { properties : ["acorn","banana","carrot"] },
notify: true
},
},
attached: function() {
console.log("update");
this.set('blocks.properties[0]', "Apple");
},
If you need to do array functions you should also use this.push(path, value) or this.splice(path, value) to notify changes.

Resources