I am trying to create an editor for a dynamic list using AngularJS. For each item I would like to add a select list containing options for all elements in the list. When an item is added to the list (Add button in the JSFiddle), the other selects lose their values. The model is not affected by this, only the view. What am I missing?
Here is my JSFiddle.
View:
<div ng-controller="selectDemoCtrl">{{msg}}
<table>
<tr>
<td>id</td>
<td>references</td>
</tr>
<tr ng-repeat="item in items">
<td>
<input ng-model="item.id" type="number">
</td>
<td>
<select ng-model="item.ref">
<option ng-repeat="i in items" value="i.id" ng-selected="item.ref==i.id">{{i.id}}</option>
</select>
</td>
</tr>
</table>
<button ng-click="addItem()">Add</button>
<div>{{items | json}}</div>
</div>
Controller:
selectDemo.controller('selectDemoCtrl', function ($scope) {
$scope.items = [{
id: 1,
ref: 2
}, {
id: 2,
ref: 1
}];
$scope.addItem = function(){
var newitem = {id: 1, ref:1};
for (var i = 0; i < $scope.items.length; i++){
if ($scope.items[i].id >= newitem.id) { newitem.id = $scope.items[i].id + 1; }
}
if ($scope.items.length > 0){newitem.ref = $scope.items[0].id;}
$scope.items.push(newitem);
};
});
Don't use ngRepeat, it's not reliable for binding model. Use ngOptions instead, it should work as expected:
<select ng-options="i.id as i.id for i in items" ng-model="item.ref"></select>
Demo: https://jsfiddle.net/4bemy5wj/1/
Related
I have a object array that I want to use in a table. I need a drop down select if the validvalues has a value. How to you do this so that each row of the table has different options from the array? If the validvalues is empty, it should be a div/input in the table row but it validvalues is not empty, it should be a dropdown with the validvalues as the options of the select.
As written, updateOptions() doesn't get called and an empty select shows on every row (insert sad emoji).
TS file
tags = [
{tagName: 'AppID', value: 'T400', validvalues: 'T100/T200/T300/T400/T500'},
{tagName: 'Series', value: 'SUPR', validvalues: ''},
{tagName: 'Collection', value: 'AUTO', validvalues: 'EFIT/AUTO/FLEET'},
{tagName: 'Function', value: 'Accounting', validvalues: 'Sales/Marketing/Accounting/Shop'},
{tagName: 'Contact', value: 'Jim Jones', validvalues: ''}]
validValuesArray: any = [];
updateOptions(parsingString: string) {
let tagValidValuesArray = parsingString.split('/');
}
HTML file
<table>
<tr>
<th>Tag Name</th>
<th>Value</th>
</tr>
<tr *ngFor="let tag of tags; let i=index">
<td>
<div>{{tag.tagname}}</div>
</td>
<td>
<div *ngIf="!tag.validvalues">
<input type="text" name="value" [(ngModel)]="tag.value">
</div>
<div *ngIf="tag.validvalues">
<select [(ngModel)]="tag.value" (ngChange)="updateOptions(tag.validvalues)">
<option *ngFor="let value of validValuesArray">{{value}}</option>
</select>
</div>
</td>
</tr>
</table>
If I understand you correctly you want your first table row to have a dropdown with the options:
T100
T200
...
Then your would have to have away to convert your string of validValues into an interable type. For example by calling validValues.split('/') this would convert your string into a string[] which you could then loop over.
Since you typically don't want to call methods in your template for performance reasons I would recommend to transform the validValues into an Array when you load them, or even before that in your database if possible unless there is a specific reason, why you would hold "a list of Options" as anything but a "listlike" data structure.
The solution is/was to load the validValuesArray after tagDtail array is loaded and then use the validValuesArray for the dropdown options. Like this...
for (var m = 0; m < this.tagDtails[0].tags.length; m++){
let currentTag = this.tagDtails[0].tags[m];
let parsingString = currentTag.validValues;
this.validValuesArray.push(parsingString.split('/'));
}
This will create an array or arrays that looks like this:
validValuesArray = [
["T100","T200","T300","T400","T500"],
[],
["EFIT","AUTO","FLEET"],
["Sales","Marketing","Accounting","Shop"],
[]]
then, in the html, loop through the validValuesArray
<tr *ngFor="let tag of tagDtails.tags; let i = index">
<td>
<div>{{ tag.tagName }}</div>
</td>
<td class="td-fix">
<div *ngIf="this.validValuesArray[i]==''">
<input type="text" class="form-control" name="tagValue" [(ngModel)]="tag.tagValue">
</div>
<div *ngIf="this.validValuesArray[i]!=''">
<select [(ngModel)]="tag.value">
<option *ngFor="let value of validValuesArray[i]">{{value}}</option>
</select>
</div>
</td>
</tr>
I want to count iteration of ng-repeat, when condition match.
I've tried $index but it print for all itration/items in nested ng-repeat
Fiddle link :https://jsfiddle.net/gdr7p1zj/1/
<tbody ng-controller="MainCtrl">
<tr ng-repeat-start="a in test1">
<td>{{a.categoryName}}(count_here)</td>
</tr>
<tr ng-repeat-end ng-repeat="b in test" ng-if="a.categoryId==b.categoryId">
<td>{{b.name}}</td>
</tr>
</tbody>
i want like this
category_one(4) <=item count 4 items in this category so 4 will display
item1
item2
item3
item4
category_two(2)
item5
item6
<!-- this is in controller -->
$scope.test1=[{
categoryId:'1',categoryName:'category one'
},
{
categoryId:'2',categoryName:'category two'
}]
$scope.test = [
{categoryId:'1',name:'cate 1 elem0'},
{categoryId:'1',name:'cate 1 elem1'},
{categoryId:'2',name:'cate 2 elem'}
];
});
An option is to create a function (getCount) in the controller which do the count, something like this:
$scope.getCount = function(categoryId) { // returns the count by matching by categoryId
return $scope.test.filter(function(element) { // first, filter elements in `test`
return element.categoryId === categoryId; // matching by categoryId
}).length; // then, return the count of how many results we got after the filter
}
And in the html call that function like this:
<tbody ng-controller="MainCtrl">
<tr ng-repeat-start="a in test1">
<td>{{a.categoryName }} ({{getCount(a.categoryId)}})</td> <!-- <-- call the function in order to display the count -->
</tr>
<tr ng-repeat-end ng-repeat="b in test" ng-if="a.categoryId == b.categoryId">
<td>{{b.name}}</td>
</tr>
</tbody>
See a demo here: https://jsfiddle.net/lealceldeiro/v9gj1ok4/11/
Thanks for your help. But i get expected output without any functions call or filters
Here fiddle Link: https://jsfiddle.net/wk3nzj96/
htmlCode:
<div ng-app='myapp' >
<div ng-controller="MainCtrl">
<table ng-init="$scope.counter=0">
<tr ng-repeat-start="cate in mainCategory">
<td> {{cate.name}} ({{$scope.counter[$index]}})</td></tr>
<tr ng-repeat="itemsItr in items" ng-init="$scope.counter[$parent.$parent.$index]=$scope.counter[$parent.$parent.$index]+1" ng-if="itemsItr.mid==cate.id">
<td>{{itemsItr.name}}</td>
</tr>
<tr ng-repeat-end ng-if="false"></tr>
</table>
</div>
</div>
and ControllerCode:
(function() {
angular.module('myapp', []).controller('MainCtrl', function($scope) {
$scope.mainCategory = [
{ name: "categoryOne",id:1 },
{ name: "categoryTwo",id:2 }
];
$scope.items = [
{ name: "item1FromCateOne" ,mid:1 },
{ name: "item2FromCateOne",mid:1 },
{ name: "item3FromCateOne" ,mid:1 },
{ name: "item1FromCateTwo",mid:2 }
];
});
Is this Standard way to do this?
I use ng-repeat to construct table with radio buttons. The idea is to assign to each radio value the position of the object inside the original array (before ordering). When I use $index it assigns position in the ordered array and not original one. How to assign the right index,original one?
<tr class="restTable" data-ng-repeat="person in persons|orderBy:'name'">
<td> {{ person.name}}</td>
<td> <input type="radio" name="radio" ng-model="$parent.selectedPerson" value="{{$index}}"/></td>
</tr>
As I wrote in the comment:
$index is relative to to the current element in the loop and since you are sorting the array then you need to save a reference on the object itself from the directive (You can use person.id for example (If you have a unique id for each person).
You can save a reference to the selected person via ngValue
angular.module('app', []).controller('ctrl', function($scope) {
$scope.selected = { person: null };
$scope.persons = [{id: 1, name: "person1"}, {id: 2, name: "person2"}, {id: 3, name: "person3"}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<table>
<tr class="restTable" data-ng-repeat="person in persons|orderBy:'name'">
<td> {{ person.name}}</td>
<td> <input type="radio" name="radio" ng-model="selected.person" ng-value="person"/></td>
</tr>
</table>
<hr>
<p>Selected Person:</p>
<pre ng-bind="selected.person | json"></pre>
</div>
Here i'm using the ngValue and saving a reference to the selected object inside the loop. I don't care about the current position of the object because angularjs is making sure the selected person will be available in the controller via $scope.selected.person.
If you want to pre select a person, replace
$scope.selected = { person: null };
With
$scope.selected = { person: $scope.persons[1] };
But don't forget to declare $scope.persons before! Put that line after you declared the array in your controller. Example:
angular.module('app', []).controller('ctrl', function($scope) {
$scope.persons = [{id: 1, name: "3person1"}, {id: 2, name: "1person2"}, {id: 3, name: "4person3"}];
$scope.selected = { person: $scope.persons[1] };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<table>
<tr class="restTable" data-ng-repeat="person in persons|orderBy:'name'">
<td> {{ person.name}}</td>
<td> <input type="radio" name="radio" ng-model="selected.person" ng-value="person"/></td>
</tr>
</table>
<hr>
<p>Selected Person:</p>
<pre ng-bind="selected.person | json"></pre>
</div>
$index won't work as it represents index of loop, not the index of item in array. So to fix this you could have index property in source or you could write a function to return related index.
var app = angular.module('app', []);
app.controller('ctrl', ['$scope', function(scope) {
scope.persons = [{
name: 'ABC index 0'
}, {
name: 'EFG index 1'
}, {
name: 'XYX index 2'
}];
scope.selectedPerson = "1";
scope.getIndex = function(item) {
return scope.persons.indexOf(item);
}
}])
angular.bootstrap(document.body, ['app']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="ctrl">
Selected Person:-
<pre>{{persons[selectedPerson] | json}}</pre>
<hr/>
<table>
<tr class="restTable" data-ng-repeat="person in persons|orderBy:'name'">
<td> {{ person.name}}</td>
<td>
<input type="radio" name="radio" ng-model="$parent.selectedPerson" value="{{$parent.getIndex(person)}}" />
</td>
</tr>
</table>
</div>
There are multiple rows in a table being created using ng-repeat. Each row has a dropdownlist. I want to get the selected value in a dropdown and attach that value with other corresponding values in the row in a string format using JavaScript or JQuery on click of Next button. eg:"one,B:two,B:three,A:four:C" (here in this example assuming B is selected for dropdown in first row,similar logic for other rows)
The below is the HTML snippet:
<div class="mainDiv" ng-controller="myController">
<div class="div1">
<table class="table myTable">
<thead>
<tr>
<th>
<center>serial</center>
</th>
<th>
<center>data</center>
</th>
<th>
<center>aplhabet</center>
</th>
</tr>
</thead>
<tbody class="myTableBody">
<tr ng-repeat="data in myData" id="{{$parent.$id+'-'+$index}}">
<td>{{$index + 1}}</td>
<td>{{data}}</td>
<td>
<select>
<option value="Select">-- Select --</option>
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
<div class="div2">
<button type="button" class="btn btn-md btn-primary btnNext">Next</button>
</div>
</div>
and below is the angularJS part:
myApp.controller('myController', function ($scope) {
$scope.myData = ["one","two","three","four"];
});
Add an ng-model={ selectData[data] }
Then update the controller with the following
$scope.selectData = {}
getResults= function() {
var returnData = $scope.myData.map(function(data) {
return data + ',' + $scope.selectData[data];
});
return returnData.join(':');
};
Switch to an object.
$scope.myData = {
one: {
id: 'one',
value: null
},
two: {
id: 'two',
value: null
},
three: {
id: 'three',
value: null
},
four: {
id: 'four',
value: null
}
}
In your HTML, add an ng-model to your select
<select ng-model="data.value">
<!-- your options, because I'm lazy -->
</select>
You will get an object containing all you want. In my opinion, I find it easier to work with objects rather than arrays.
I would like to get which checkbox are selected by the user, i have this table but it dosen't work. is there any alternative ?
<table class="table table-bordered table-hover" style="max-height: 500px; overflow-y: auto" border="1">
<tr>
<th> Nom Exigence</th>
<th> Verifier</th>
</tr>
<tr data-ng-repeat="item in list" style="background-color: #F5F5F5">
<td>
{{item.Nom}}
</td>
<td>
<input type="checkbox" checklist-model="user.list" />
</td>
</tr>
</table>
verify
Close
when i try to log the $scoepe.user.list it shows me []
this is the modal controller
app.controller('ModalInstanceExigencesCtrl', function ($scope, $modalInstance, list) {
$scope.list = [];
$scope.user = [];
for (var i = 0; i < list.length; i++) {
$scope.list.push(list[i]);
}
console.log($scope.list);
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.verify = function () {
console.log($scope.user);
};
});
this Fiddle should do the job for u: jsfiddle example using checkboxes
Html-Code (pretty similiar to ur code):
<div ng-controller="MainCtrl">
<ul>
<li ng-repeat="item in items">
<label class="checkbox">
<input type="checkbox" ng-model="items[$index].checked" />
{{item.name}}
</label>
</li>
</ul>
<hr class="space clearfix" />
{{items | json}}
JS-Code:
var app = angular.module('angularjs-starter', []);
function MainCtrl( $scope )
{
$scope.items = [
{ name:'foo', checked: true },
{ name:'bar' },
{ name:'baz' }
];
}
I just define one $scope Object called items. In my example each item has a name and optional a value checked, which determines wether a checkbox is checked or not.
Html is pretty forward, we repeat over all items and then bind our checkbox model ng-model="items[$index].checked". $index gives us the number of iteration, for example our first iteration binds to ng-model="items[0].checked"
Hope that helps.
You can try by using this way also
Html-Code:
$scope.collectNumbers = function (contact, index) {
if (contact.IsChecked) {
}
else{
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<tr class="" ng-repeat="contact in Contacts">
<td>
<label>
<input type="checkbox" ng-model="contact.IsChecked" ng-change="collectNumbers(contact,$index)" ng-checked="contact.IsChecked">
</label>
</td>
<td>{{contact.Name}}</a></td>
</tr>