I am making a CRUD in angular + Php + MySql where I am facing a problem.
I have some data in database and want to show it on listing page.
To achieve this I made a ajax call in Angular and put the response in Scope Variable. If I print response its showing me below response but not able to show it in HTML. I am getting a problem i.e., :-
Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: person in crew, Duplicate key: string:", Duplicate value: "\""
Below is the Angular and HTML code :-
.controller('wrapperController', ['$scope','$rootScope','$http', function(scope,rootScope,http){
http.post("server/viewRecords.php")
.success(function(response){
console.log(response);
scope.crew = response;
});
}])
<tr ng-repeat="person in crew">
<td>{{person.name}}</td>
<td>{{person.desc}}</td>
<td> Edit </td>
<td> Delete </td>
</tr>
Please suggest why I am getting this error?
Thanks!!
AngularJS does not allow duplicates in a ng-repeat directive. Therefore, you can add track by $index into the ng-repeat as following:
<tr ng-repeat="person in crew track by $index">
<td>{{person.name}}</td>
<td>{{person.desc}}</td>
<td> Edit </td>
<td> Delete </td>
</tr>
Track by $index tells angular to use $index, which is auto increment, as a key instead of each individual element in the array. So, it won't be duplicate anymore.
Related
I have an array that looks like the following:
I want to display that using angularJS ng-repeat, showing both count and value for each.
This is currently the HTML and angular I have but nothing displays.
I also don't need to display the 0 index in the array, I want to start from 1 if possible.
<tr ng-class="" ng-repeat="x in vm.data | filter: searchArray">
<td>{{x.value}}</td>
<td>{{x.count}}</td>
</tr>
I went back to the basics and understood that an ng-repeat is just a loop in javascript, and what do you need to do if you want to access data in JavaScript if your array is multi-dimensional? well you do a nested for loop, and thats exactly what I'm doing in this case.
This is the updated html/angularjs that displays the data I need:
<tbody>
<tr ng-repeat="x in vm.data">
<td ng-repeat="y in x">{{y.value}} {{y.count}}</td>
</tr>
</tbody>
Thank you guys again!
Try to present all data with ng-repeat from web service.
This is my controller JS (GetAllCtrl.js):
I get JSON data:
Now I want to get only company data without coupons data
(Company structure in JSON is: compName, id, email, coupons[])
In GetAllCtrl.js I have put the data in allComp variable.
This is GetAllCtrl.html:
I do ng-repeat in tr tag and use $index for loop on the array with data.
But in output, I get only 2 companies instead 4.
In clonsole.log I see 4 objects.
I'm new in AngularJS and JS and can't understand why it happened.
You are iterating over the wrong variable. It should be ng-repeat="c in getAllCtrl.allComp.data" and correspondingly change your td elements.
<tr ng-repeat="c in getAllCtrl.allComp.data track by $index">
<td align="center"><b>c.compName</b></td>
<td align="center"><b>c.id</b></td>
<td align="center"><b>c.email</b></td>
</tr>
I have a Filter for a Table and want to show no Results if the filter found nothing.
In short the necessary Code:
<th>Keys
<input ng-model="k" id="search" class="form-control" placeholder="Suche...">
</th>
<tr dir-paginate="v in result = ($ctrl.langV | filter:{Name:k}) | orderBy : 'Name' |itemsPerPage: 10">
<td class="td-keys">{{v.Name}}
</td>
<td ng-if="result.length === 0">Keine Ergebnisse</td>
I have found allready here a few Examples:
Show message if text filter return no result in ng-repeat
How to show a message when filter returns nothing in ng-repeat - AngularJS
AngularJS - placeholder for empty result from filter
But none of them working?
A simple
<td ng-show="result.length">Keine Ergebnisse</td>
Is showing me the extra td because results are found. But the opposite for no Results never works.
Thx for Solutions :)
Why don't you use like this... when no results, this would show.
<td ng-if="!result.length">Keine Ergebnisse</td>
In the three examples you referenced, they are displaying the no result message outside of the ng-repeat. You are display the no result message inside the ng-repeat. Try taking that statement out of the scope of the ng-repeat and see if it works then.
At first you have to give an alias to your "results", something like filteredItems, as below:
<tr dir-paginate="v in $ctrl.langV | filter: { Name: k } | orderBy : 'Name' | itemsPerPage: 10 as filteredItems">
Then, you can use it:
<td ng-if="!filteredItems.length">No results</td>
I am making a custom directive which will paginate and make my table sortable. I am trying to make it so that multiple data types will work with the sorting with no effort from the user. Here is my problematic html in my templateUrl:
<tr ng-repeat="row in cndPaginatedObject track by $index">
<td ng-repeat="data in row track by $index" ng-if="!isValidDate(row[cndTableHeaders[$index]])">
{{row[cndTableHeaders[$index]]}}
</td>
<td ng-repeat="data in row track by $index" ng-if="isValidDate(row[cndTableHeaders[$index]])">
{{row[cndTableHeaders[$index]] | date: cndDateFormat}}
</td>
</tr>
I would prefer to use ng-if as opposed to ng-show/hide because it would unnecessarily duplicate DOM elements with ng-show/hide and just not show them. I have tried both ways, but I get the same result either way. The content of columns with dates in them don't show up, but the td itself is still there taking up space. So, I end up having three headers for columns and more than three columns. As far as I was aware, ng-if is supposed to remove the entire element from the DOM.
here is my other code of significance:
scope.isValidDate = (data) => {
var timestamp = Date.parse(data);
return !(isNaN(timestamp));
}
As for cndPaginatedObject, it is just an array of objects with multiple strings contained within. Thank you for any help in advance!
UPDATE:
Just thought I would also add that the cndTableHeaders is literally the table headers. cndPaginatedObject uses the table headers as the keys to each of the values. This way they show up in the proper order in the table.
Two ways to do what you're doing better without the need to produce extra doms and looping a ng-repeat twice
A better way to do what you want to do is
<tr ng-repeat="row in cndPaginatedObject track by $index">
<td ng-repeat="data in row track by $index">
{{(!isValidDate(row[cndTableHeaders[$index]])) ? row[cndTableHeaders[$index]] : row[cndTableHeaders[$index]] | date: cndDateFormat}}
</td>
</tr>
Or add a span inside the with the ng-if logic
<tr ng-repeat="row in cndPaginatedObject track by $index">
<td ng-repeat="data in row track by $index"">
<span ng-if="!isValidDate(row[cndTableHeaders[$index]])>
{{row[cndTableHeaders[$index]]}}
</span>
<span ng-if="isValidDate(row[cndTableHeaders[$index]])">
{{row[cndTableHeaders[$index]] | date: cndDateFormat}}
</span>
</td>
</tr>
Alternatively you could create your own filter which checks if date is valid and then using the date filter to filter it.
I am trying to make an entirely dynamic angularJS page in such a way that the data-model and header-column-model can be passed in as JSON format and the angular/view can decode everything no matter how many columns, etc.
I have everything (Column Headers, single-Column sorting, multi-Column textbox filtering) working except the data portion where it looks like I want to nest {{bindings}}.
The idea is something like this:
<tr ng-repeat="item in model | filter:filters | orderBy:predicate:reverse">
<td ng-repeat="header in headers">{{{{$parent.item}}.{{header.colName}}}}</td>
</tr>
So that it would resolve to item.column (which is how this is done normally/statically).
However, there doesn't seem to be any embedding/nesting allowed for the double-squiggle references; aka. the first '{{' matches with the first '}}' automatically.
Is there a [good] way to do this?
Try using $eval:
<tr ng-repeat="item in model | filter:filters | orderBy:predicate:reverse">
<td ng-repeat="header in headers">{{$eval('item.' + header.colName}}</td>
</tr>
Here is a plunker showing that concept:
http://plnkr.co/edit/msGuMCCj477jyUAqjChz?p=preview