How to repeat object properties in angular ui-select-choices? - angularjs

I have an object as
{
key1: value1,
key2: value2
}
How will repeat this in ui-select-choices? I tried a few things but nothing worked as
<ui-select ng-model="selectedChoice" theme="select2">
<ui-select-match placeholder="{{'select_product' | translate}}" allow-clear="true">
<span ng-bind="$select.selected"></span>
</ui-select-match>
<ui-select-choices repeat="key as (key, value) in (productList | filter: $select.search)">
<span>{{::key}}</span>
</ui-select-choices>
</ui-select>

This should work:
<ui-select-choices repeat="product.key as (key, product) in productList | filter: {'value':$select.search}">
<span ng-bind-html="product.value"></span>
</ui-select-choices>
Angular UI Select iterates over objects kinda this way: during iterating for each pair (key, value) instead of accessing the value directly, an object (it's named product in my code above) is created that consists of two properties named key and value, where key is an actual key of the initial object, value is a value for the key. This object should be used to access a real value.
For example, for the following initial data object
{
key1: {
id: 1,
name: 'John'
},
key2: {
id: 2,
name: 'Alex'
}
}
on the first iteration such object will be created:
{
key: 'key1',
value: {
id: 1,
name: 'John'
}
}
For your data object, the following object will be created on the first iteration (product):
{
key: 'key1',
value: 'value1'
}

Related

Angular Use Function in Container Context

I want to set up a checkbox structure and I want to handle it dynamically. I have an object response returned from my service. However, when I use this function in context, I get a string return and I cannot use ngFor.
form.demo.component.ts
getElementChoicesByNKey(nkey:string):choiceModel[]{
var element = this.findInComponentsByNKey(nkey);
var res = element.Choices;
return res;
}
this function gives the correct return.
form.demo.component.html
...
<ng-container *ngIf="item.Type == 'Choice'">
<ng-container *ngTemplateOutlet="choiceTheme; context:{ Id: item.Id, Label: item.Label, Choices: getElementChoicesByNKey(item.Id) }"></ng-container>
</ng-container>
...
<ng-template #choiceTheme let-Id="Id" let-Label="Label" let-Choices="Choices">
<nz-form-item>
<nz-form-label nzFor="Id">{{Label}}</nz-form-label>
<nz-form-control [formControlName]="Id" nzErrorTip="{{ 'form.requiredText' | translate }}">
<p>{{Choices.length}}</p>
<div *ngFor="let item of Choices">
<p>test</p>
</div>
</nz-form-control>
</nz-form-item>
</ng-template>
...
here Choices appears as string and won't let me use ngFor. I am getting an error as below.
Cannot find a differ supporting object '[
{ label: 'Apple', value: 'Apple', checked: true },
{ label: 'Pear', value: 'Pear', checked: false },
{ label: 'Orange', value: 'Orange', checked: false } ]' of type 'string'. NgFor only supports binding to Iterables such as Arrays.
What is the point I missed? Thank you for your help.
Use
*ngFor="let item of getChoices(Choices)" in template
and in component.ts
getChoices(choiceStr) {
return JSON.parse(choiceStr);
}
Since you are getting Choices as a string, parse the string to an array inorder for ngFor to work

AngularJS toArray converts object keys to numbers

I use angular-filter in my project to sort the output objects by page the problem is when I use syntax like this:
<ul class="catalog-list"
ng-repeat="(key, value) in list | groupBy: 'styl' | toArray | orderBy:'page'">
{{key}}
<li ng-repeat="dziecko in value | filter:search | bookmark:search"
ng-class="{active:isActiveTab(dziecko)}"
ng-click="openItem(dziecko)">
{{dziecko.rodzina}}
<b>{{dziecko.page}}</b>
</li>
</ul>
Angular converts 'styl' properties ['nowoczesny','klasyczny'..] to numbers. Sorting works fine but I want to obtain names instead of numbers.
groupBy return an object, and orderBy expect array as an argument, so that's the reason you should use toArray filter.
toArray work like that:
Usage: object | toArray: addKey[optional]
if addKey set to true, the filter also attaches a new property $key to the value containing the original key that was used in the object we are iterating over to reference the property
So, you can do something like this example, or take a look on the jsbin
JS:
$scope.groups = [
{ category: 'alpha', id: 2 },
{ category: 'beta', id: 3 },
{ category: 'gamma', id: 0 },
{ category: 'alpha', id: 4 },
{ category: 'beta', id: 5 },
{ category: 'gamma', id: 1 }
];
HTML:
<ul ng-repeat="group in groups | groupBy:'category' | toArray:true | orderBy:min">
<!-- print the group name -->
<li>{{ group.$key }}</li>
<!-- iterate over the group members and order each group by id -->
<li ng-repeat="item in group | orderBy:'id'">
{{ item }}
</li>
</ul>
RESULT:
alpha
{"category":"alpha","id":2}
{"category":"alpha","id":4}
beta
{"category":"beta","id":3}
{"category":"beta","id":5}
gamma
{"category":"gamma","id":0}
{"category":"gamma","id":1}
An array has no named keys. It has integers as position. So don't use toArray.

Angular ngOptions and filter

I'm trying to filter an array on ngOptions:
Here a plunkr: http://plnkr.co/edit/OxL84mDdma9iS13wMnIX?p=preview
I have this array:
$scope.keys = [ {
id: 1,
name: 'ddddggggggggggggggggg',
applicationKey: 'dssssssssssssss',
kind: 'pingdom',
} , {
id: 2,
name: 'Ddd',
kind: 'moz',
accessId: 'ssss',
secretKey: 'aaaa',
} , {
id: 3,
name: 'MyAlexa',
kind: 'alexa',
secretAccessKey: 'ssssssssssssssssss',
accessKeyId: 'ssssssss',
}
]
And I'm trying to filter using somethig like this:
<select name="key" ng-model="keys"
ng-options="k.name for k in keys track by k.id | filter: {kind: 'alexa'}" >
</select>
Perhaps you might want to do the following:
<select name="key"
data-ng-model="keys"
data-ng-options="key.name for key.name in keys | filter: { kind: 'alexa' } track by key.id">
</select>
You must have the track by after you apply the filter.
EDIT:
The only issue you had in your markup is the track by expression being before the filter. The rest of differences are just personal preferences.
Try this code.
<select name="key" ng-model="keys"
ng-options="k.name for k in keys | filter: {kind: 'alexa'}" >
</select>

Filter in ng-options not working

I have an object that maps IDs to their objects. I would like to display the list of these object and use a filter, but I cannot get it to work. Specifically, I'm trying to prevent object with ID 2 from appearing in the options Here's what I've got:
http://jsfiddle.net/9d2Za/
<div ng-app ng-controller="ctrl">
Unfiltered:
<select ng-model="selectedBidType"
ng-options="bidType.id as bidType.label for (bidTypeID, bidType) in bidTypes">
</select>
<br>
Filtered:
<select ng-model="selectedBidType"
ng-options="bidType.id as bidType.label for (bidTypeID, bidType) in bidTypes | filter:{id: '!2'}">
</select>
</div>
Please note: I cannot change the structure of the bidTypes object in whatever fix we come up with. Here's my AngularJS:
function ctrl($scope)
{
$scope.selectedBidType = 1;
// Bid type objects are indexed by ID for fast lookup (this cannot be changed in solution)
$scope.bidTypes = {
1: {id: 1, label: "Buy"},
2: {id: 2, label: "Sell"},
3: {id: 3, label: "Missing"}
};
}
As described by the documentation, the filter filter only accepts an array as first parameter, not an object. In such cases, I personally use a custom filter to make the transformation:
myModule.filter(
'objectToArray',
[
function ()
{
return function (object)
{
var array = [];
angular.forEach(object, function (element)
{
array.push(element);
});
return array;
};
}
]
)
;
And then, in the template:
<select ng-options="… in bidTypes | objectToArray | filter:{id:'!2'}">

NgRepeat filtering complex structure

I have been given a complex JSON object to display inside Angular and I'd like to filter it into two lists after having drilled down into the object.
The object structure is:
{
foo:
{
bar:
{
showA: { value: true, type: 'A' },
showB: { value: false, type: 'A' },
showC: { value: true, type: 'A' }
}
}
}
And I'm trying to achieve a list of "false" and "true".
In this case:
Disabled:
showB - Type: A
Enabled:
showA - Type: A
showC - Type: A
I can't filter the object and also can't obtain the "key" of the objects, e.g. "showA".
My attempt of using:
item in profile['foo']['bar'] | filter: { value: false }
Accesses the correct objects but I can't filter or get the "key" of it.
Here is a broken plunkr to demonstrate:
http://plnkr.co/edit/9NniQdo213AuEbf0pghA?p=preview
Any advice would be great!
Check out this working punkr: http://plnkr.co/edit/TdM9P592OXd6Bx81Bmbt?p=preview
It uses a custom filter, myFilter, which makes the filtering task pretty simple. myFilter returns a new object with only the objects having value equal to the value given as second argument to the filter.
app.filter('myFilter', function() {
return function(bar, value) {
var r = {};
for (var key in bar) {
if (bar[key].value == value) {
r[key] = bar[key];
}
}
return r;
}
});
To get the key with ng-repeat, use the following syntax:
<li ng-repeat="(key, item) in profile['foo']['bar'] | myFilter:false">
<input type="checkbox" ng-model="item.value" /> {{ key }}
</li>
If you can alter the structure of $scope.profile, the filtering task would be easier with this structure:
bar: [
{name: 'ShowA', value: false, type: 'A'},
...
]

Resources