Set dynamic id with $index - html

I've got this code:
My list, wich should work like a navigation with main nav points and sub nav poins:
list = [
{
Id: 1,
Name: 'Main 1',
Items: [
{
Id: 1,
Name: 'Sub 1'
},
{
Id: 2,
Name: 'Sub 2'
}
]
},
{
Id: 2,
Name: 'Main 2',
Items: [
{
Id: 1,
Name: 'Sub 1'
},
{
Id: 2,
Name: 'Sub 2'
}
]
}
];
And this is my HTML. I loop the main poins and it's sub points with ng-repeat and try to set some id's dynamicly with the $index.:
<div class="wrapper" ng-repeat="item in list">
<div id="main_{{$index}}">{{item.Name}}</div>
<div id="main_{{$parent.$index}}_sub_{{$index}}" ng-repeat="sub in item.Items">
<div>— {{sub.Name}}</div>
</div>
</div>
My result is something like this and it works fine:
Main 1
- Sub 1
- Sub 2
Main 2
- Sub 1
- Sub 2
My goal is now to assign a id to my div with the main and my div with the subs. I add the current index with $index to my id in the main div and after that I try to combine the id for the sub divs with the index from the main (it's parent) and the current index. To get the index of the parent, I used $parent.$index. My expected result are follow id's:
Main 1 -> id = main_0
- Sub 1 -> id = main_0_sub_0
- Sub 2 -> id = main_0_sub_1
Main 2 -> id = main_1
- Sub 1 -> id = main_1_sub_0
- Sub 2 -> id = main_1_sub_1
But this doesn't work at the moment. The id's for the main div is correct, but the id for the sub isn't. I thought with $parent.$index it should work, but there is a problem with the current index of the main. I have no idea how to solve this. I hope someone can help me.

Try the below code snippet, it's working fine here !
var app = angular.module('app',[]);
app.controller('Ctrl',function($scope){
$scope.list = [
{
Id: 1,
Name: 'Main 1',
Items: [
{
Id: 1,
Name: 'Sub 1'
},
{
Id: 2,
Name: 'Sub 2'
}
]
},
{
Id: 2,
Name: 'Main 2',
Items: [
{
Id: 1,
Name: 'Sub 1'
},
{
Id: 2,
Name: 'Sub 2'
}
]
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl">
<div class="wrapper" ng-repeat="item in list">
<div id="main_{{$index}}">{{item.Name}} - main_{{$index}}</div>
<div id="main_{{$parent.$index}}_sub_{{$index}}" ng-repeat="sub in item.Items">
<div>— {{sub.Name}} - main_{{$parent.$index}}_sub_{{$index}}</div>
</div>
</div>
</div>

I notice that what you want is have the $index-1. Try this:
<div class="wrapper" ng-repeat="item in list">
<div id="main_{{$index-1}}">{{item.Name}}</div>
<div id="main_{{$parent.$index-1}}_sub_{{$index-1}}" ng-repeat="sub in item.Items>
<div>— {{sub.Name}}</div>
</div>
</div>

Related

How to preselect PrimeNG Checkbox items?

I am not able to get already selected item. In this code in rp which is an array of type Permission which has one element in it , So basically that value should be selected when I load this div. What will be the mistake?
This is My HTML:-
<div class="gapRowSmall displayFlex flexColumn mb-small" *ngIf="(permissions$ | async)! as permissions">
<div *ngFor="let permission of permissions" class="p-field-checkbox">
<p-checkbox [value]="permission" [(ngModel)]="rp" class=" mr-small"></p-checkbox>
<label>{{permission.name}}</label>
</div>
<div class="displayFlex flexJustifyEnd">
<p-button type="submit" label="Save" styleClass="primary" (onClick)="savePermissions()"
[appSubmitIndicator]="(isSubmitInProgress$ | async)!"></p-button>
</div>
</div>
This is My ts file:-
permissions$ = this.store.select(permissionSelector)
.pipe(takeUntil(this.permissionManagementSubject));
rp: Permission[] = [{ name: 'Create New Transitions', id: 'a45d7806-fbf8-4df7-8248-6f636288ff23' },];
The item in your rp array must completely match one of the items in your Observable permissions array. If not all the fields in the object match, then it will not be selected.
So if the permissions would be loaded in the constructor like this:
constructor() {
this.permissions$ = of([
{name: "aaaaa", id: '123456-789012'},
{name: "bbbbb", id: '223456-789012'},
{name: "ccccc", id: '323456-789012'}
])
}
and the selected permissions in rp would be :
rp: Permission[] = [
{ name: 'aaaaa', id: '123456-789012' },
{ name: 'bbbbb', id: '223456-' }, // This one is incomplete, thus no match
];
Then the second one, will not be selected although partially it is matching.
I've a working example of this in stackblitz. https://stackblitz.com/edit/primeng-checkbox-demo-9rhzru?file=src/app/app.component.ts

How can I get display varying number of data elements of a specific attribute in Vue js?

I have a product listing which I am looping on using v-for. These products have headlines and top features. A headline-top feature can look something like this on my webpage:
PRODUCT 1
**First headline**
This is the description of the feature of product 1 under the first headline
**Second headline**
This is the description of the feature of product 1 under the second headline
**Third headline**
This is the description of the feature of product 1 under the third headline
PRODUCT 2
**First headline**
This is the description of the feature of the product 2 under the first headline.
**Second headline**
This is the description of the feature of the product 2 under the second headline.
THE PROBLEM: The number of headline-top feature for each product could vary, like PRODUCT 1 has 3 headline-top feature and PRODUCT 2 has 2 headline-top feature. I am not quite sure how I could specify these varying number of headline-top feature in my Vue app. I have something like this:
Product_listing.vue
<template>
<div class="content">
<div class="nested" v-for="product in products">
<div class="one">{{product.Name}}</div>
<div class="two"> {{product.headline}}</div> ---->
<div class="three"> {{product.top_feature}}</div> ----> I think I need a loop here? Not sure how?
</div>
</div>
</template>
<script>
export default {
data () {
return {
products:[
{id: 1, Name: 'Product 1',
Headline_1:'Headline 1', top_feature_1: 'This is the description of the feature of product 1 under the first headline',
Headline_2:'Headline 2', top_feature_2: 'This is the description of the feature of product 1 under the second headline',
Headline_3:'Headline 3', top_feature_3: 'This is the description of the feature of product 1 under the third headline'
},
{id: 2, Name: 'Product 2',
Headline_1:'Headline 1', top_feature_1: 'This is the description of the feature of product 2 under the first headline',
Headline_2:'Headline 2', top_feature_2: 'This is the description of the feature of product 2 under the second headline',
}
and so on...
]
}
},
created: function() {
axios.get('ajaxfile.php')
.then(function (response) {
app.products = response.data;
})
.catch(function (error) {
console.log(error);
});
}
}
})
</script>
I would really appreciate some help here. Thanks!
The solution above via reshaping data can solve this problem,and i have easier way to solve it,getting a total keys prior then loop the total keys in the template,and display the fields which have varying number by dynamic.
new Vue({
el: "#app",
data: {
products: [
{
id: 1,
Name: 'Product 1',
Headline_1: 'Headline 1',
top_feature_1:
'This is the description of the feature of product 1 under the first headline',
Headline_2: 'Headline 2',
top_feature_2:
'This is the description of the feature of product 1 under the second headline',
Headline_3: 'Headline 3',
top_feature_3:
'This is the description of the feature of product 1 under the third headline',
},
{
id: 2,
Name: 'Product 2',
Headline_1: 'Headline 1',
top_feature_1:
'This is the description of the feature of product 2 under the first headline',
Headline_2: 'Headline 2',
top_feature_2:
'This is the description of the feature of product 2 under the second headline',
},
],
},
computed: {
},
created(){
this.products.map(product => {
const totalKeys = Object.keys(product).length;
product.totalKeys = totalKeys
});
console.log('this.products', this.products)
},
methods: {
}
})
<div id="app">
<div class="content">
<div class="nested" v-for="product in products">
<div class="one">{{product.Name}}</div>
<div class="two" v-for="num in product.totalKeys">
<p v-if="product['Headline_'+num]">{{product['Headline_'+num]}}</p>
<div class="three"> {{product['top_feature_'+num]}}</div>
</div>
</div>
</div>
</div>
<b>https://jsfiddle.net/happy9527/a0rjgp6y/</b>
Assuming the data returned from your axios call has the same shape as the products example, the easiest solution is to reshape the data prior to using it in the template. You can do this using a computed property. Here's a complete working example:
<template>
<div class="content">
<div v-for="product in productsWithHeadlines" :key="product.id">
<div>{{ product.name }}</div>
<ul>
<li v-for="(headline, index) in product.headlines" :key="index">
<div>{{ headline.text }}</div>
<div>{{ headline.feature }}</div>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data() {
return {
products: [
{
id: 1,
Name: 'Product 1',
Headline_1: 'Headline 1',
top_feature_1:
'This is the description of the feature of product 1 under the first headline',
Headline_2: 'Headline 2',
top_feature_2:
'This is the description of the feature of product 1 under the second headline',
Headline_3: 'Headline 3',
top_feature_3:
'This is the description of the feature of product 1 under the third headline',
},
{
id: 2,
Name: 'Product 2',
Headline_1: 'Headline 1',
top_feature_1:
'This is the description of the feature of product 2 under the first headline',
Headline_2: 'Headline 2',
top_feature_2:
'This is the description of the feature of product 2 under the second headline',
},
],
};
},
computed: {
// Returns `products` with the following structure:
// {
// id: Number,
// name: String,
// headlines: [
// text: String,
// feature: String,
// ],
// }
productsWithHeadlines() {
return this.products.map(product => {
const totalKeys = Object.keys(product).length;
const headlines = [];
for (let index = 1; index < totalKeys; index += 1) {
const text = product[`Headline_${index}`];
const feature = product[`top_feature_${index}`];
if (text && feature) headlines.push({ text, feature });
}
return {
id: product.id,
name: product.Name,
headlines,
};
});
},
},
};
</script>

Angular 6 :material checkbox checked all checkbox in loop

In loop
<li *ngFor="let item of verticalList;let i=index;">
<mat-checkbox [(ngModel)]="checked" name="i">Checked</mat-checkbox>
</li>
I want to give each checkbox a different checked value. How to do it?
I don't know what is verticalList type, but id you use a list of object you could do something like this:
verticalList = [
{
name: 'foo',
checked: false
},
{
name: 'foo1',
checked: false
},
{
name: 'foo2',
checked: false
}
]
<li *ngFor="let item of verticalList;let i=index;">
<mat-checkbox [(ngModel)]="item.checked" name="i">Checked {{ item.name }}</mat-checkbox>
</li>

Bootstrap multiselect dropdown does not work inside div having ng-repeat

I want to use bootstrap multiselect dropdown for selecting multiple values for parameters . I am using it like -
<div ng-repeat="param in parameters">
<div>{{param.name }} :</div>
<div ng-show = "param.multipleValues">
<select ng-model="param.value" id="testMultiSelect" multiple="multiple">
<option ng-repeat="v in values" value="{{v}}" >{{v}}</option>
</select>
</div>
<div ng-show = "!param.multipleValues">
<input type="text" ng-model="param.value">
</div>
</div>
But , somehow , multiselect is not working inside ng-repeat. If I put it outside of this div having ng-repeat , it works.
It comes like in image -
This may helps you
var app = angular.module('testApp', [ ]);
app.directive('telDropdownmutiple', ['$http', function ($http) {
return {
restrict: 'E',
scope: {
array: '=',
validate: '#',
ngModel: '=',
title: '#',
checkId: '#',
ngmaxLength: '#',
ngminLength: '#',
lblvalue: '#',
textboxSize: '#',
lblSize: '#',
ngShow: '#',
textboxtype: '#',
getString: '#',
multiple: '#',
},
template:'<div id="{{ checkId }}" > <span>{{ title }}</span>:<select {{ multiple }} class="{{className}}" ng-model="ngModel" ng-options="a[optValue] as a[optDescription] for a in array" requireiftrue="{{ validate }}"></div>'+
'<option style="display: none" value="">{{title}}</option>' +
'</select> </div>',
link: function (scope, element, attrs) {
scope.lblvalue = attrs.lblvalue;
scope.title = attrs.title;
scope.optValue = attrs.optValue;
scope.optDescription = attrs.optDescription;
}
};
}]);
app.controller('testController', ['$scope', '$location', function ($scope, $location) {
$scope.SelectMultiple = [
{Id: 1, Description: "option1"},
{Id: 2, Description: "option2"},
{Id: 3, Description: "option3"},
{Id: 4, Description: "option4"},
{Id: 5, Description: "option5"},
{Id: 6, Description: "option6"},
{Id: 7, Description: "option7"},
{Id: 8, Description: "option8"},
{Id: 9, Description: "option9"},
{Id: 10, Description: "option10"}
];
}]);
<script data-require="angular.js#~1.3.15" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js"></script>
<body class="hold-transition skin-blue sidebar-mini" data-ng-app="testApp">
<!-- Logo -->
<!-- Left side column. contains the logo and sidebar -->
<div class="content-wrapper" style=" margin-top: 50px; margin-bottom: 10px; height: 350px; overflow-y: auto; " ng-controller="testController">
<tel-Dropdownmutiple multiple ng-model="registration.multipledropGender" lblvalue="Gender" array="SelectMultiple" opt-value="Id" opt-description="Description" validate='true' class-Name="form-controlselect select2" ></tel-Dropdownmutiple>
</div>
</body>

Checking for equality in Angular filter

I have objects similar to the ones listed below:
fields = [{id: 1}, {id: 2}, {id: 3}]
rules: [{name: "A", field: {id: 1}}, {name: "B", field: {id: 2}}]
And I want to filter each of the rules out by individual field IDs. Right now I have:
<div ng-repeat="f in fields">
<h4>{{f.id}}</h4>
<li ng-repeat = "rule in rules | filter: {field.id: f.id}">
{{rule.name}}
</li>
</div>
However, the following filter returns no elements. How do I make the filter show the rules that have field.id equal to f.id?
Use this instead:
<div ng-repeat="f in fields">
<h4>{{f.id}}</h4>
<li ng-repeat = "rule in rules | filter:{ field: {id: f.id} }">
{{rule.name}}
</li>
</div>
Match the object structure in the filter.
Here is the demo where I have added another property age (int) to prove the fact that filter only works on id.