how to update elements containing relation - angularjs

I have scope like below
$scope.phones = [
{
id: 4,
name: "nokia",
accessories: [
{id: 1, name: "headset"},
{id: 3, name: "keyboard"},
{id: 5, name: "charger"}
]
},
{
id: 5,
name: "samsung",
accessories: [
{id: 5, name: "charger"}
]
},
{
id: 6,
name: "iphone",
accessories: [
{id: 1, name: "headset"},
{id: 5, name: "charger"}
]
}
];
For example they are displayed like
-> Phone name
-> accesories
Now my case
If I update accessory that is in relation with phone I want to update records that are displayed but only those that are in relation with updated accessory. I don't want to update whole action view but only records that are bound with the updated accessory
How can I do that ?
// edit
I've created a manual workaround
$scope.editAcc = function (idx) {
for(var i = 0; i < $scope.phones.length; i++) {
var tmpPhone = $scope.phones[i];
for(var j = 0; j < tmpPhone.accessories.length; j++) {
var acc = tmpPhone.accessories[j];
if(acc.id == idx) {
acc.name = acc.name + " Z";
}
}
}
// var acc = $scope.accessories[idx];
// acc.name = acc.name + " X";
};
But IMO there should be some function to do that

I don't think there is a built-in way to update the value by JSON path, but you can at least use angular.forEach() to loop through the collections:
$scope.editAcc = function (idx) {
angular.forEach($scope.phones, function (t) {
angular.forEach(t.accessories, function(acc){
(acc.id == idx) ? (acc.name += " Z") : null;
});
});
}
DEMO

Related

Angular2: loop through a recently pushed array and push from another

I have an array object
MainArray = {"Data":
[{"Group": "GroupA"},{"Group": "GroupB"}]
}
then I loop through the array and created a new
let _newArray : any[] = [];
MainArray.Data.forEach(item => {
_newArray.push({
groupname : item.Group,
columns: ["column1","column2","column3"]
});
//loop through _newArray.columns
});
then I need to loop through the columns of new Array inside the Main Array loop
and push an array from another..
SecondArray = [{group: "GroupA", value: "firstfield", count: 14 },{group: "GroupA", field: "secondfield", count:23 },{group: "GroupB", field: "randomfield", count:1 }]
so the output should be
_newArray = [{
groupname: "GroupA",
columns: ["column1","column2","column3"]
col1: [{"firstfield":14, "secondfield": 23 }]
col2: "",
col3: ""
},{GroupB...}]
what I tried:
Object.keys( _newArray[0].columns).forEach( function(value, key) {
console.log(this._SecondArray[item.Group])
// push 'col + index: [Second Array]'
});
In your SecondArray the first object is having a 'value' key. I assumed it as "field"
let MainArray = {
"Data":
[{ "Group": "GroupA" }, { "Group": "GroupB" }]
}
// First push
let _newArray = [];
MainArray.Data.forEach(item => {
_newArray.push({
'groupname': item.Group,
'columns': ["column1", "column2", "column3"]
})
})
let SecondArray = [{ group: "GroupA", field: "firstfield", count: 14 }, { group: "GroupA", field: "secondfield", count: 23 }, { group: "GroupB", field: "randomfield", count: 1 }];
// Second push
_newArray.forEach(item => {
console.log(item)
let i = 1;
item.columns.forEach(cols => {
console.log(cols)
if (i == 1) {
item["col" + i] = {}
SecondArray.forEach(subItem => {
console.log(subItem)
if (subItem.group == item.groupname) {
item["col" + i][subItem.field] = subItem.count
}
})
i++
} else {
item["col" + i++] = ""
}
})
})
console.log(_newArray);

Filter an Array based on multiple values

I have the following simple JSON array:
const personList = [
{
id: 1,
name: "Phil"
},
{
id: 2,
name: "Bren"
},
{
id: 3,
name: "Francis Underwood"
},
{
id: 4,
name: "Claire Underwood"
},
{
id: 5,
name: "Ricky Underwood"
},
{
id: 6,
name: "Leo Boykewich"
}
];
And I would like to filter this by passing an array of ids so something like [1,4] would be passed in and it would only return "Phill" and "Claire Underwood"
This is what the function looks like but I know it's wrong attendeeIds is an array that's passed in [1, 4]:
getAttendeesForEvent: (attendeeIds) => {
if (attendeeIds === undefined) return Promise.reject("No attendee id provided");
return Promise.resolve(personList.filter(x => x.id == [attendeeIds]).shift());
}
I haven't used JS in years. I've looked for examples but they all seem too complex for what I'm trying to achieve. So how can I filter this based on an array of id's passed in?
return Promise.resolve(personList.filter(x => attendeeIds.indexOf(x.id) !== -1));
You want to check if the id of each item your looping over exists inside of attendeeIds. Use Array.indexOf inside of the filter to do that.
This will return an array of { id: #, name: String } objects.
If you want to return just the names of those objects, you can do a map afterwards which will transform an array into another array using the function that you provide.
const filteredNames = personList
.filter(x => attendeeIds.indexOf(x.id) !== -1)
.map(x => x.name);
// ['Phil', 'Claire Underwood']
You could do something in these lines. Hope this helps.
const personList = [{
id: 1,
name: "Phil"
}, {
id: 2,
name: "Bren"
}, {
id: 3,
name: "Francis Underwood"
}, {
id: 4,
name: "Claire Underwood"
}, {
id: 5,
name: "Ricky Underwood"
}, {
id: 6,
name: "Leo Boykewich"
}];
let attendeeIds = [1, 5];
let getAttendeesForEvent = () => {
return new Promise(function(resolve, reject) {
if (attendeeIds === undefined) {
reject("No attendee id provided");
} else {
resolve(personList.filter((x) => attendeeIds.includes(x.id)).map((obj) => obj.name));
}
});
}
getAttendeesForEvent().then((data) => console.log(data))

Kendo-ui grid filtering

I am trying to filter items in a grid by tags, the data in the grid looks like this
[
{ id: 0, tags: [{ text: 'boat' }, { text: 'summer' }] },
{ id: 1, tags: [{ text: 'boat' }] },
{ id: 2, tags: [{ text: 'travel' }] },
{ id: 3, tags: [{ text: 'boat' }] },
{ id: 4, tags: [{ text: 'travel' }] },
{ id: 5, tags: [{ text: 'travel' }, { text: 'summer' }] }
]
And the function for filtering looks like this
$scope.filterGrid = function (e) {
var grid = $('#imageGrid').data('kendoGrid');
var val = [{ text: 'travel' }, { text: 'summer' }];
grid.dataSource.filter({});
if ($.trim(val) !== '') {
grid.dataSource.filter({
logic: 'or',
filters: [{
field: 'tags',
operator: function (item) {
var status = false;
for (var n = 0, length2 = val.length; n < length2; n++) {
for (var i = 0, length = item.length; i < length; i++) {
if (item[i].text.indexOf(val[n].text) !== -1) {
status = true;
break;
}
}
}
return status;
}
}]
});
}
};
With this example where val = travel, summer i would like to only show the items with both tags (id 5) but it shows all items containing either of the tags (id: 0,2,4,5)
What am i doing wrong and is there a better way to do this with kendo?
Your filter algorithm was accepting the item to have at least one of the two desired values, because the loop break when find one here:
if (item[i].text.indexOf(val[n].text) !== -1) {
status = true;
break;
}
I have changed a little your code to this:
operator: function (item) {
var found = 0;
for (var i = 0, length = item.length; i < length; i++) {
for (var n = 0, length2 = val.length; n < length2; n++) {
if (item[i].text.indexOf(val[n].text) !== -1) {
found++;
break;
}
}
}
return found == val.length;
}
It counts the total of found tags(found) and return true only if the number of found items is the same as the search items(val.length). So it starts iterating through item, and not through val, as the rule stands for the item has to be all the values, and not the way around. So for each item is performed a check if it has all val items and sum found counter. At the end, if found is equal val.length it means that all items on val are inside item.
Working demo

Retrieving tree node text in KendoUI/Angular

The objective of this plunk is to query a specific tree node (given its id stored in the variable sk) and show an alert with its text. Enter a number in the input field (the node sk value), click on the button and you should see an alert with the node text.
The get method and hasChildren in the hierarchical data source are not working, any ideas?
HTML:
<div kendo-tree-view k-data-source="treeData"></div>
<br/><br/>
<button ng-click="queryTree()">Get Text</button>
<input ng-model="sk">
Javascript:
function MyCtrl($scope) {
$scope.sk = 3;
$scope.treeData = new kendo.data.HierarchicalDataSource({
data: [
{ sk: 11, text: "Furniture", expanded:true, items: [
{ sk: 2, text: "Tables & Chairs"},
{ sk: 3, text: "Sofas" },
{ sk: 4, text: "Occasional Furniture" }
] },
{ sk: 12, text: "Decor", expanded:true, items: [
{ sk: 6, text: "Bed Linen" },
{ sk: 7, text: "Curtains & Blinds" },
{ sk: 8, text: "Carpets" }
] }
],
schema: {
model: {
id: "sk",
hasChildren: function(item) {
return item.sk > 10;
}
}
}
});
$scope.queryTree = function(){
$scope.treeData.fetch(function() {
var dataItem = $scope.treeData.get($scope.sk);
alert(dataItem.text);
});
};
}
You should access the datasource directly:
$scope.queryTree = function(){
var nodeDataItem = $scope.treeData.get($scope.sk);
alert(nodeDataItem.text)
};
Here is a working plunkr for you. http://plnkr.co/edit/N4FYVh227HjvYOoWMYo4

How to remove items in one array if other has it?

How to remove item from array B if array A has it. I want to iterate through by ID.
array A: it has all the items
[{
"Name":"John",
"Id":1
},
{
"Name":"Peter",
"Id":2
},
{
"Name":"Phillip",
"Id":3
},
{
"Name":"Abby",
"Id":4
},
{
"Name":"Don",
"Id":5
}]
array B: has just the selected items
[{
"Name":"John",
"Id":1
},
{
"Name":"Abby",
"Id":4
}]
I want to remove from array A John and Abby by Id, because they are in array b.
for (var i = 0; i < a.length; i++) {
if (b[i].Id == ta[i].Id) {
for (var j = 0; j < b[j]; j++) {
a.splice(i, 1);
}
}
}
this is not working as I thought
You could first get all id's of person objects in b:
let idsInB: number[] = b.map(person => person.Id); // > [1, 4]
This array of id's can be used to filter a, and then assign the result back to a. Let's contain that in a function cleanA:
function cleanA(): void {
let idsInB: number[] = b.map(person => person.Id);
a = a.filter((person) => -1 === idsInB.indexOf(person.Id));
}
All you need to do now is call cleanA whenever the contents of b changes.
Full working example:
interface Person {
Id: number;
Name: string;
}
let a: Person[] = [
{ Id: 1, Name: "John" },
{ Id: 2, Name: "Peter" },
{ Id: 3, Name: "Phillip" },
{ Id: 4, Name: "Abby" },
{ Id: 5, Name: "Don" },
];
let b: Person[] = [
{ Id: 1, Name: "John" },
{ Id: 4, Name: "Abby" },
];
function cleanA(): void {
let idsInB: number[] = b.map(person => person.Id);
a = a.filter((person) => -1 === idsInB.indexOf(person.Id));
}
presentArray(a, 'A before clean');
cleanA();
presentArray(a, 'A after clean');
// -------------------------------------------------------
// Displaying purposes only:
// -------------------------------------------------------
function presentArray(arr, msg) {
document.body.innerHTML += `<br><b>${msg}:</b><br>[<br>`
+ arr.map(person => ` { Id: ${person.Id}, Name: ${person.Name} },<br>`)
.join('')
+ ' ]<br><br>';
}

Resources