Repeating multidimensional array object in angular - arrays

I have an array that looks like this:
[Object{ 82893u82378237832={ id=8, no=1, type="event", name="Sample1"}}, Object{ 128129wq378237832={ id=9, no=1, type="event", name="Sample2"}} ]
Now ignoring the first part which is just a random token i want to get the array inside that. i.e. id,no,type,name and display them in an ng-repeat, how can i achieve this?
This is how i create the above array:
var obj = {};
obj[data.responseData] = {
id: 8,
no: 1,
type: 'event',
name: ''
}
$scope.items.push(obj);

Your example doesn't include an array.
Anyway here's a good example.
Use map to transform an array to another array and use ng-repeat in a similar way that I've done.
Html:
<div ng-app="app">
<div ng-controller="ctrl">
<div ng-repeat="item in myArr">
{{item}}
</div>
</div>
</div>
JS:
angular.module('app', []).
controller('ctrl', function ($scope) {
var arr = [{
myId: '82893u82378237832',
id: 8,
no: 1,
type: "event",
name: "Sample1"
}, {
myId: '128129wq378237832',
id: 9,
no: 1,
type: "event",
name: "Sample2"
}];
// mapped the new object without myId
$scope.myArr = arr.map(function (item) {
return {
id: item.id,
no: item.no,
type: item.type,
name: item.name
}
});
});
JSFIDDLE.

Related

Skip duplicated items while ng-repeat

There is a nested array which consist of bundles and those bundles in turn have items. So, I want to skip identical item(s) of the next bundle based on previous bundle items while iterating. Below is data model and code snippets:
vm.data
[
{
id: '01',
name: 'Dummy1',
items: [{
id: 'itemOne',
name: 'ItemOne',
desc: 'ItemOne description'
}]
},
{
id: '02',
name: 'Dummy2',
items: [{
id: 'itemOne',
name: 'ItemOne',
desc: 'ItemOne description'
},
{
id: 'otherItem',
name: 'OtherItem',
desc: 'OtherItem description'
}]
},
...
]
Html:
<div ng-repeat="bundle in vm.data track by $index">
...
<ul>
<li ng-repeat="item in bundle.items" ng-if="vm.check(item, $parent.$index)">
<span ng-bind="item.name"></span>
...
</li>
</ul>
</div>
vm.check:
vm.check = function(item, bundleIdx) {
if (bundleIdx > 0) {
return _.some(vm.data[bundleIdx-1].items, function(obj) {
return obj.id !== item.id;
});
} else {
// first bundle, so show all items
return true;
}
};
Demo is here.
It works partially, i.e. second bundle correctly matches conditions, but third bundle not. So, what I'm missing? Any help would be appreciated!
I would keep the complex logic out of your template. Instead you should transform vm.data before you attempt to consume it.
var items = {};
vm.bundles = [];
vm.data.forEach(function(data) {
var bundle = {
id: data.id,
name: data.name,
items: []
};
data.items.forEach(function(item) {
if (!items[item.id]) {
bundle.items.push(item);
}
items[item.id] = true;
});
vm.bundles.push(bundle);
});
Then your template can simply consume the transformed data.
<div ng-repeat="bundle in vm.bundles track by $index">
...
<ul>
<li ng-repeat="item in bundle.items">
<span>{{item.name}}</span>
...
</li>
</ul>
</div>

Angularjs: evaluate expression inside HTML tag

Note this question is a bit different from the similar titled here or here. What I want to do is to "evaluate inside the HTML tag" not inside a directive (or in the controller). This description can be wrong or hard to understand but I cannot find a better way; so I made bellow self-contained code to illustrate. You may copy and past and save as "xyz.html" and see what I mean.
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.6/angular.min.js"></script>
<script>
'use strict';
let app = angular.module('myApp', []);
app.controller('myCtrl', ['$scope', function ($scope) {
let d = DATA_TYPE;
let e = EDIT_TYPE;
$scope.tbContents = {
fields: [
{name: 'name', dataType: d.text, editType: e.text, refs:[]},
{name: 'catalog', dataType: d.text, editType: e.dropdown, refs: ['catalog1', 'catalog2', 'catalog3']},
{name: 'status', dataType: d.int, editType: e.dropdown, refs: [1, 2, 3, 4]}],
rows: [
{name: 'name1', catalog: 'catalog1', status: 1},
{name: 'name2', catalog: 'catalog1', status: 1},
{name: 'name3', catalog: 'catalog2', status: 2}
]
};
$scope.refNameKey = '';
$scope.setRefNameKey = function(key) {
$scope.refNameKey = key;
};
$scope.getRefByNameKey = function(key) {
let res = [];
for(let i = 0; i < $scope.tbContents.fields.length; i++) {
if($scope.tbContents.fields[i].name == key) {
return $scope.tbContents.fields[i].refs;
}
}
};
}]);
app.filter('filterDropdown', function () {
return function (fields) {
let output = [];
for (let i = 0; i < fields.length; i++) {
if (fields[i].editType == EDIT_TYPE.dropdown) {
output.push(fields[i]);
}
}
return output;
};
});
const DATA_TYPE = {
int: 1,
text: 2,
//...
};
const EDIT_TYPE = {
dropdown: 1,
test: 2,
//...
};
</script>
</head>
<body>
<div ng-controller="myCtrl">
<div>
<!--<p ng-repeat="field in tbContents.fields | filterDropdown">{{field.name}}</p>-->
<p ng-repeat="field in tbContents.fields | filterDropdown">{{field.name}}</p>
</div>
<hr />
<div ng-show = "refNameKey">
<p ng-repeat = "ref in getRefByNameKey(refNameKey)">{{ref}}</p>
</div>
</div>
</body>
</html>
What I want is the line I commented in the HTML code, refNameKey=field.name instead of setRefNameKey(field.name). I don't know why refNameKey=field.name does not work, but I don't like creating the setRefNameKey function for this simple task.
ng-repeat creates child scope for each iteration. So your refNameKey variable is created in each child scope and its not referring to the refNameKey in parent scope. You can fix this by modifying it like this:
<p ng-repeat="field in tbContents.fields | filterDropdown">{{field.name}}</p>
Plunker : http://plnkr.co/edit/mcDvGqd6SFCfmqyfUNRc?p=preview

selected option is not getting displayed Angularjs dropdownlist

When I am using an object where I have property which has selectedOptions it is not getting displayed in the dropdownlist. However, when I put in scope and select from the object then it displayed. Anyone has any idea why the first one is not working. Here is the plunker link.
http://plnkr.co/edit/XLuXmAmh4F9OobyJhBCW?p=preview
var app = angular.module('angularjs-starter', []);
var model = {
options : [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'blah' }],
selectedOption : { id: 1, name: 'foo' }
}
app.value('vm',model);
app.controller('MainCtrl', function($scope,vm) {
$scope.vm =vm;
$scope.items = [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'blah' }];
$scope.selectedItem = $scope.items[1];
});
<body ng-controller="MainCtrl">
<h1>Select something below</h1>
<select id="s1" ng-model="selectedItem" ng-options="item as item.name for item in items"></select>
<h3>The selected item:</h3>
<pre>{{selectedItem | json}}</pre>
<h3>The inner html of the select:</h3>
<pre id="options" class="prettify html"></pre>
<select data-ng-options="o.name for o in vm.options" data-ng-model="vm.selectedOption"><option value="">Select one</option></select>
<pre>{{vm.selectedOption | json}}</pre>
</body>
Angular uses strict comparison (===) to evaluate if given option is to be selected. It will only if the value of selectedItem is the same as the option's one. And in JavaScript, if you create two objects of the same structure and try to strictly compare it, they are not the same, i.e.:
{a: 1} !== {a: 1}
In the second example you're keeping the reference to the original object insted, so it would be like doing this:
var obj1 = {a: 1};
var obj2 = obj1;
obj1 === obj2;

using ng-model in ng-repeat angularjs

I am having some problems with angular. Now I have a following code :
<div ng-repeat='item in items'>
<span>{{item.title}}</span>
<input ng-change="test()" ng-model='abc'> {{abc}}
<span>{{item.price| currency}}</span>
<span>{{item.price * item.quantity| currency}}</span>
<button ng-click="remove($index)">Remove</button>
</div>
<script type="text/javascript" src="libs/angular.min.js"></script>
<script>
function CartController($scope) {
$scope.items = [
{title: 'Paint pots', quantity: 8, price: 3.95},
{title: 'Polka dots', quantity: 17, price: 12.95},
{title: 'Pebbles', quantity: 5, price: 6.95}
];
$scope.test = function() {
console.log($scope.abc);
}
$scope.remove = function(index) {
$scope.items.splice(index, 1);
}
}
</script>
I wanna know why I can not console.log abc value in controller? My English is bad, pls help me. Thanks in advance
Try changing
$scope.test = function() {
console.log($scope.abc);
}
to
$scope.test = function() {
console.log(this.abc);
}
"this" will resolve to the current scope object and you should be able to print the value as you keep changing the text.
What happens if you declare abc as a variable before trying to use it?
function CartController($scope){
var $scope.abc = 'foo';
...

exact filter in angular

In Angular, is there a way to modify the filter such that it only returns exact matches?
Example:
var words = [
{ title: "ball" },
{ title: "wall" },
{ title: "all" },
{ title: "alloy" }
];
var wordsFiltered = filter('filter')
(
words,
{
'title': 'all'
}
);
The above will match 'ball', 'wall', 'all' and 'alloy'. But I would like it to only match 'all'. Any way to change it?
UPDATE
Starting from AngularJS v.1.1.3 the exact filtering is provided natively:
Find words that exactly match title:
<input ng-model="match.title" />
<br>
and exactly match type:
<input ng-model="match.type" />
<hr>
<table>
<tr ng-repeat="word in words | filter:match:true">
<td>{{word.title}}</td>
</tr>
</table>
Plunker
Your question implies that you would want to match against multiple object properties so here's a filter that does that:
app.controller('AppController',
[
'$scope',
function($scope) {
$scope.match = {};
$scope.words = [
{ title: "ball", type: 'object' },
{ title: "wall", type: 'object' },
{ title: "all", type: 'word' },
{ title: "alloy", type: 'material' }
];
}
]
);
app.filter('exact', function(){
return function(items, match){
var matching = [], matches, falsely = true;
// Return the items unchanged if all filtering attributes are falsy
angular.forEach(match, function(value, key){
falsely = falsely && !value;
});
if(falsely){
return items;
}
angular.forEach(items, function(item){ // e.g. { title: "ball" }
matches = true;
angular.forEach(match, function(value, key){ // e.g. 'all', 'title'
if(!!value){ // do not compare if value is empty
matches = matches && (item[key] === value);
}
});
if(matches){
matching.push(item);
}
});
return matching;
}
});
<body ng-controller="AppController">
Find words that exactly match title:
<input ng-model="match.title" />
<br>
and exactly match type:
<input ng-model="match.type" />
<hr>
<table>
<tr ng-repeat="word in words | exact:match">
<td>{{word.title}}</td>
</tr>
</table>
</body>
PLUNKER
Try this :
var words = [
{ title: "ball" },
{ title: "wall" },
{ title: "all" },
{ title: "alloy" }
];
var wordsFiltered = filter('filter')
(
words,
{
'title': 'all'
},
true
);
You can use Regex to achieve a simple implementation:
<input ng-model="query" />
<tr ng-repeat="word in words | filter: myFilter">
In the controller:
$scope.myFilter = function (word) {
if ($scope.query === '') return true;
var reg = RegExp("^" + $scope.query + "$");
return reg.test(word.title);
};
I would create a new filter. Is this what you want?
HTML
<div ng-controller="MyCtrl">
{{words | exactMatch:'all'}} !
</div>
JavaScript
var myApp = angular.module('myApp',[]);
myApp.filter('exactMatch', function() {
return function(words, pattern) {
var result = [];
words.forEach(function (word) {
if (word.title === pattern) {
result.push(word);
}
});
return result;
}
});
function MyCtrl($scope) {
$scope.words = [
{title: "ball", other: 1},
{title: "wall", other: 2},
{title: "all", other: 3},
{title: "alloy", other: 4},
{title: "all", other: 5},
];
}
JsFiddle: jsfiddle
More information about custom filters: filters, creating custom filters and using filters
If you want use filter in Javascript instead of html you should look here: jsfiddle
I created my own filter.
<select
ng-model="selection.neType"
ng-options="option.NE_TYPE_ID as option.NAME for option in networkElementTypes">
<option value="">Todos</option>
</select>
<select
ng-model="selection.neTypeVendor"
ng-options="option.VENDOR_TYPE_ID as option.NAME for option in networkElementTypeVendors | exactMatch: {FK_NE_TYPE_ID: selection.neType}">
<option value="">All</option>
</select>
app.filter('exactMatch', function() {
return function(elements, pattern) {
var result = [];
var fieldSearch = Object.keys(pattern)[0];
elements.forEach(function (element) {
if (element[fieldSearch] == pattern[fieldSearch]) {
result.push(element);
}
});
return result;
}
});
angular-filter is a useful library of filters.
One of their filters is the where filter that does an exact match.

Resources