Can I stop Angular binding failing silently? - angularjs

I have the following table markup:
<tr ng-repeat="client in clientsIndex">
<td>{{client.fullName}}</td>
<td>{{item.contactPhone}}</td>
</tr>
When the view for this renders, I see only one column is populated, but nothing logged in the console. Is there a way I can tell angular this is a debugging session, and I'd like to see big screaming error messages if I make a copy and paste mistake?

Surely at the time the {{}} expression is evaluated whatever does that can output a non-blank value at least?
As of Angular 1.1.5 there is support for ternary operators in templates. So you can define something like this to get a default value if undefined:
<tr ng-repeat="client in clientsIndex">
<td>{{client.fullName}}</td>
<td>{{item.contactPhone ? item.contactPhone : 'Error: not defined'}}</td>
</tr>
The general structure is: {{(condition) ? (expression if true) : (expression if false)}}.

For debugging purpose you can select the element using any angular.element("") selectors and see the scope of that element to check the variable you are trying to access inside the element is inside the scope available to that element.Find the example below.i have used an id selector you can use a child selector.
<tr id="canbeReplacedWithChildSelectors" ng-repeat="client in clientsIndex">
<td>{{client.fullName}}</td>
<td>{{item.contactPhone}}</td>
</tr>
angular.element("#canbeReplacedWithChildSelectors").scope() execute this and check client.fullName is available in the scope.in your case angular.element("#canbeReplacedWithChildSelectors").scope().client would give you undefined.

Related

Is the AngularJS smart-table documentation/demo buggy?

I just don't understand this. On the smart-table web page, where it discusses the stSafeSrc
attriubute, I don’t see where $scope. displayedCollection gets declared.
The text says smart-table first creates a safe copy of your displayed collection, and I
I had assumed that a smart-table directive was declaring it, but the sample code won’t work for me – the table rows are empty - and that’s what looks to me to be the problem.
If we look, for instance, at the accepted answer to this question, we see the user declaring $scope.displayedCollection as an empty array and assigning it a value when the AJAX response is received. BUT, the documentation doesn't mention that.
<table st-table="displayedCollection" st-safe-src="rowCollection">
<thead>
<tr>
<th st-sort="firstName">First Name</th>
<th st-sort="lastName">Last Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in displayedCollection">
<td>{{row.firstName}}</td>
<td>{{row.lastName}}</td>
</tr>
</tbody>
</table
app.controller('Ctrl', function($scope, service) {
$scope.displayedCollection = [];
service.all.then(function(list) {
$scope.rowCollection = list;
$scope.displayedCollection = list;
});
});
So, do I need to care for the copy myself? And does the documentaion need to be updated? And how does the demo work?
[Update] I find this on the github issues, by #tufan-yoc
you have to copy the data array to an other variable in the scope:
st-table="displayedCollection" st-safe-src="rowCollection"
and
//copy the references (you could clone ie angular.copy
// but then have to go through a dirty checking for the matches)
$scope.displayedCollection = [].concat($scope.rowCollection);
If this truly is a requirement, why is it not explictly documented?
And why does the example on the smart-table website work without it?
You don't need to copy anything. what you set with the attribute st-table is simply a placeholder for your templates (ie a variable in the scope) which you will likely use in the row repeater, it does not have to be declared anywhere, smart-table will assign the items to be displayed to this variable so your templates can be updated.
your source of truth (ie your data) should be the collection you bind to st-safe-src attribute. Whenever the bound collection changes, smart table will update a local copy so it can perform the filter/sort/slice operations based on the latest and actual data.
However for convenience (and performance), if you don't intend to modify your data (or its arrival is not delayed like with ajax fetch) the internal copy is firstly based on any collection bound to the variable in the scope designed by the st-table attribute.
Note in this case, the value will be erased and replaced by the displayed collection so the template is updated. Fortunately the initial copy will persist as private variable of smart-table.
If you encounter a problem it likely comes from somewhere else. If so please provide a running example (with angular version and smart table version)
No, it's not buggy. SmartTables will create an $scope.displayedCollection object or whatever name you use for the array that will hold a copy of the original data if you use the stSafeSrc attribute. If it doesn't show you any data check your rowCollection object, it should contain the original array. If you are working in Chrome try the ng-inspector for AngularJS so you can see the scope of your app. Also if you could post a plunker of your code it will be better.
We can show that the user must take action to make acopy and keep it in synch with AJAX data, by looking at this Plunk (which is not mine).
If we comment out line 18:
$scope.displayedCollection = [].concat($scope.rowCollection);
as per the online example, the table becomes empty.
Conclusion: the website documentation is wrong to say
smart-table first creates a safe copy of your displayed collection
And, bizarrely, the (working) example on the website ... should not work (?)

ng-repeat value as ng-class for last <td>

<tr ng-repeat="row in rows">
<td ng-class="{row[th]:$last}" ng-repeat="th in ths">{{row[th]}}</td>
</tr>
for the code above, i'm trying to use the row[th] value as the name of the class in ng-class for the last td element only.
I can use an actual class name just fine, but not the referenced value from row[th]. Any ideas how to accomplish this?
PS: the row[th] will return a status (e.g. Red, Green, etc.), which is also a css class name i'm using.
jsFiddle here
in the fiddle above, if i replace row[th] with Green in ng-class, that works!
the solution below by #tasseKATT works fine, however now i seem to have another issue. i'm not able to include another static-named class. Fiddle link here. Any help much appreciated.
After much troubleshooting, I came up with the following solution (extending #tasseKATT's original answer:
<td ng-class="{true: [row[th], 'staticCSSClassName']}[$last]" ng-repeat="th in ths">{{row[th]}}</td>
The code above adds two classes to the last <td> in ng-repeat:
value contained in row[th]
staticCSSClassName
So, basically, the value part in the Object can be an array of strings, which can include referenced values from ng-repeat as well as static class names.
working jsfiddle here
Hope someone finds this useful.

Angularjs ng-class not updating when using object annotation style

I just noticed that something doesn't work in Angular (or it doesn't as I expected it to work) when using object in ng-class.
What do I expect?
When changing the name of a property in the object, the class should update accordingly.
What did I try?
I found that when I use object style annotation like
ng-class="{obj.prop: testExpression}" and the obj.prop changes (the expression keeping returning TRUE) the value inside ng-class changes but that in the class attribute doesn't.
the difference is between this [NOT WORKING]:
<tr ng-repeat="user in users" ng-class="{ {{user.genre}}: true}">
and this [WORKING]:
<tr ng-repeat="user in users" ng-class="user.genre">
See a plunkr here:
http://plnkr.co/edit/149ba2WQ5RK5XqLmWQWK?p=preview
The thing is I need to use object annotation in order to disable the class.
Is there something I am doing wrong or I just misunderstood Angular?
Or a third solution?
In short, { {{user.genre}}: true} is not a correct angularjs expression
For your solution, try ng-class="getClass(user.genre)"
and do whatever you want in getClass function
example
You are trying to evaluate an object here, hence for each key-value pair of object with a real (truthy) value the corresponding key is used as a class name. If you have single parameter you have to use like:
<tr ng-repeat="user in users" ng-class="user.genre: true">
In case of multiple parameter you have to use like:
<p ng-class="{strike: deleted, bold: important, red: error}">

Dynamic table using ui-if

Have a look at the following code:
1.
<th ui-if="testBool">Test</th>
Problem with this snippet is that gets generated and the ui-if only includes or excludes the value test but not the whole table header.
2.
<div ui-if="testBool">
<th>Test</th>
</div>
This always shows the div nevertheless the value of testBool.
So is it possible to dynamically include th/tr's in a table?
Angular already has a directive ngIf for this. The element on which ng-if is placed only gets rendered if ngIf holds true else it does not.
<th ng-if="testBool">Test</th>
You should be using atleast version 1.1.5 for this.

Angular JS Skip OrderBy Value

I have the following code
<tr>
<th ng-click="predicate='-name'; reverse=false;">Name</th>
<th ng-click="predicate='age'; reverse=true;">Age<th>
<tr>
<tr ng-repeat="user in users | orderBy:predicate:reverse">
<td>{{user.name}}<td>
<td>{{user.age}}</td>
</tr>
My aim here is whenever i click on the table header, then the corresponding column has to be sorted based on particular predicate and reverse. And that is happening perfectly. But I have a scenario where, when i click on an external object, then my age value in table changes here and hence as a result the table sort order is getting disturbed. But i don't want sort to get disturbed. How can i skip table to not obey sort on other actions and have it only on click of table column headers? Can anyone help me with this?
I don't think this is possible. Whenever "users" changes, Angular will notice (since that scope property (i.e., "users") is bound (one-way data binding) to the ng-repeat directive), and Angular will update the view.

Resources