I'm a beginner at Angularjs and I would like to know how can I use javascript built-ins like Date or Array in expressions. It seems weird to add them like this $scope.Array = Array in every controller.
Edit: In response to your comment below, I would just add a little change to the way you have done it as I personally like to remove as much logic as possible from the view.
JavaScript
$scope.numItems = 5;
$scope.range = Array($scope.numItems);
HTML
<tr ng-repeat="i in range track by $index">
<td align="center">{{$index}}</td>
Related
I have a simple ng-repeat with a filter on it below. However in my html I see my logic in the html. Is there a way to hide this?
<div ng-repeat="row in rowData.players| filter:{name:"Dan"})">
{{row.name}}
</div>
When I look at my page though all my repeated divs have the above logic expression in them. Is there a directive or best practice to hide this?
<div ng-repeat="row in rowData.players| filter:{name:'Dan'})">
{{row.name}}
</div>
Try using single quotes instead of double quotes.
You have an extra ")" at the end of your:
"row in rowData.players| filter:{name:'Dan'})"
not sure if it has to be there or not, check it out, also #Divyesh is right, try to use simple ticks '' instead of "" when already enclosed by doble ticks
Rather than filtering in your html template, you can create a scoped variable that holds these filtered values, and then iterate over them. That way users who inspect your DOM will not see the filtered values.
For example, in your controller, you could have:
.controller('SomeCtrl', function($scope, $filter) {
$scope.rowData.players = $filter('someFilter')(filterArgs1, filterArgs2, etc);
})
HTML
<table ng-show="ecu.dtcs">
<tbody>
<tr>
<td colspan="4">
<uib-accordion close-others="true">
<uib-accordion-group ng-repeat="dtc in dtcList track by $index">
...
</uib-accordion-group>
</uib-accordion>
</td>
</tr>
</tbody>
</table>
<uib-pagination
total-items="{{ totalItems }}"
ng-model="{{ currentPage }}"
items-per-page="{{ itemsPerPage }}"
boundary-link-numbers="true"
ng-change="setPagingData(currentPage)">
</uib-pagination>
JS (directive)
link: function (scope) {
scope.showEcuDetails = function (ecu) {
// For pagination
scope.itemsPerPage = 20;
scope.totalItems = ecu.dtcs.length;
scope.currentPage = 1;
scope.setPagingData = function(currentPage) {
var start = (currentPage - 1) * scope.itemsPerPage,
end = currentPage * scope.itemsPerPage;
scope.dtcList = ecu.dtcs.slice(start, end);
};
scope.setPagingData(scope.currentPage);
};
}
ecu.dtcs: Holds all the data that I want
dtcList: Holds the sliced list each 20 elements
I have used the Angular-Bootstrap documentation and have also referenced this source (except have used ng-change to alter the list instead of a $watch on the scope)
I have debugged the application thoroughly and I can see that dtcList is becoming populated wiht the first 20 elements. However, going into the HTML, there is nothing displayed
I have also tried to write a .filter (like is shown here) but because the variables are being set in the scope of the directive and not a controller, my filter, cannot see the variables
N.B: For the pagination settings, to reference the scope variables (i.e. totalItems), I have used Angular expressions like displayed in this question and also basic strings as in the documentation (i.e. "totalItems")
I think the concepts and the way I have it written at the moment should work, it's just the HTML cannot see dtcList for some reason
EDIT
It may help to know that this is in an angular-ui-bootstrap modal. Below the function call to setPagingData(), I have this:
$uibModal.open({
templateUrl: "ecuDialog.html",
size: "lg",
windowClass: "modalDialogs networkTest__largeContentDialog",
scope: scope
});
The templateUrl is that of which I've written in the HTML section of this question. It crossed my mind whether this was the issue but my colleagues have assured me that it would not impact the result in any way.
EDIT 2
Unfortunately, 1 of our colleagues who specialises in AngularJS has viewed the code along with the documentation and cannot see any errors within it. Could it be an Angular bug or is it the combination of multiple elements from angular-ui-bootstrap that it doesn't like?
Things I am combining are:
ui-modal
ui-accordion
ui-pagination
Solution:
My code was correct. My colleague had an attempts at it and just took the code I had written into another directive. We were both unsure why this was the case, maybe Angular doesn't like overcrowded directives?
I've only started learning angular. I decided to upgrade my 1.2 examples to the current version. I spotted that filter doesn't work anymore. It broke in 1.3.6.
I'm no longer able to filter by 2 fields of collection objects.
http://plnkr.co/edit/Mpo5UDvzjUWIToTZo142?p=preview
<li class="animate-repeat" ng-repeat="friend in friends | filter:{age:a,name:q }">
How to get this behaviour back? Ultimately I want ng-repeat to display custom directives enclosing content of each friend.
Will the filter work when I reformat my code?
thanks
Your code is perfectly working. You should simply not forget to initialize the variables used in the filter predicate, since they are supposed to be strings, according to the documentation:
// In the controller
$scope.a = '';
$scope.q = '';
As a side note, please use more meaningful names for your variables.
<tr ng-repeat="rows in DATA1">
<INEEDSOMETAG ng-repeat="(key,part) in rows" ng-switch on="key">
<td ng-switch-when="ABCD" ng-repeat="piece in part">{{piece}}</td>
<td ng-switch-default>{{part}}</td>
</INEEDSOMETAG>
</tr>
this information is parsed from a json object which one of the 'parts' is another object and i need to iterate through that but display them as another 'td'.
obviously one way to go would be to provide some sort of dynamic tag if thats possible ('INEEDSOMETAG')
json below:
{obj1: {
ABCD:{
x:'x',
y:'y'
},
a:'a',
b:'b',
c:'c',
d:'d',
},
obj2:{
ABCD:{
z:'x',
f:'y'
},
a:'a',
b:'b',
c:'c',
d:'d',
},
}
added a jsfiddle: http://jsfiddle.net/kDF5L/1/
A couple issues to begin with:
Your <span> tags aren't properly balanced; they all end with </td>.
$scope.js isn't valid Javascript. An object must contain key/value pairs, so I think you should use an array of objects instead.
If you really wanted to go this way (and as the commentators suggest, this doesn't look like the most Angular approach to accomplishing whatever you're trying to do) - I've made a JSFiddle that demonstrates how you can make the code start doing something.
If you're still interested in making a custom element like <i-need-some-tag> (I'm assuming you wouldn't need to at this point, although knowing how to do this is pretty fundamental to the framework), you need write a custom directive. How to do that is sort of beyond the scope of this question, but there's a lot of resources on Stack Overflow, Google, and the AngularJS docs on how to do this. You'd start out with something like this:
.directive("INeedSomeTag", function() {
return {
restrict: 'E', // used like <i-need-some-tag>
replace: true,
template: `<td>...</td>`
}
});
And like charlietfl said, you might be able to pass in the <td> elements into the directive definition object's template property.
I'm stuck on something that I was expecting with AngularJS to work out of the box without any issues, and yet strangely enough...
I'm using a JSON service that returns data as a 2D array:
$scope.data= [
["val-11", "val-12", "val-13"],
["val-21", "val-22", "val-23"]
];
From this I'm trying to generate a table like this:
<table>
<tr ng-repeat="row in data">
<td ng-repeat="col in row">{{col}}</td>
</tr>
</table>
I don't understand why AngularJS doesn't handle such a basic scenario. I can get correct $index for the parent loop, if I need it, I can iterate through the values, but only with one loop like this "col in data[0]", but I cannot get any result trying to use the nested loop as shown above.
Am I doing something wrong? It just seems to be too basic not to work right away. Please somebody help me with this bizarre issue.
In Angular 1.0.x the ng-repeat directive had numerous bugs caused by trying to "guess" whether non-object values (i.e. strings or numbers) had been added, removed or moved.
The problem is that non-objects have no identity of their own, so it is impossible to track them accurately. This was problematic in a number of cases and also caused the ngRepeat code to be bloated with loads of workarounds and edge cases.
In 1.2 we improved the syntax for ng-repeat to allow the developer to specify for themselves exactly how to identify items in a collection. This is done by the "track by" keyword. One consequence of this is that we disallow items which have the same identifier.
By default ng-repeat will try to track by the value of the item. If you have repeated items such as the same object or identical strings or numbers then ng-repeat will complain and you will see the error in the console.
var TableCtrl = function($scope) {
$scope.data= [
["", "", "val-13"]
];
}
Here the first two items in the sub-array are the same "empty" string. See this fiddle: http://jsfiddle.net/tEU8r/
If you really do want to have repeated items in the collection then you need to provide a method for ng-repeat to distinguish them. The simplest and obvious approach is to track the items by their position in the collection. This is done by using "track by $index". Here is the same example but fixed in this way:
<table ng-controller="TableCtrl">
<tr ng-repeat="row in data">
<td ng-repeat="col in row track by $index">
{{$parent.$index}}-{{$index}} {{col}}
</td>
</tr>
</table>
http://jsfiddle.net/h44Z8/
So this is not a bug in AngularJS. But you are correct that people should be aware of this change when upgrading to 1.2