I have a javascript list var myElements = [1, 2, 3] and want to get a string like the following one:
<th>
<tr>QC</tr>
<tr>1</tr>
<tr>2</tr>
<tr>3</tr>
</th>
As can been seen, the QC is not an element in the list but I want to insert that before the ng-repeat elements. It seems that I cannot do this by adding ng-repeat to the parent element (<th>). I tried to use ng-repeat-start and ng-repeat-end like this:
<th>
<tr>QC</tr>
<tr ng-repeat-start="myElement in myElements" ng-repeat-end ng-bind="myElement"></tr>
</th>
But it didn't work.(FIXED: it works.. but looks clumsy..)
Does anyone have ideas about how to do this in AngularJS? Thanks!
Have you tried with just ng-repeat?
<tr>
<th>QC</th>
<th ng-repeat="myElement in myElements" ng-bind="myElement"></th>
</tr>
Related
So I am trying to render an array of objects with handlebars in my node app, and it seems to be picking up the objects since table rows are being added to the DOM, but none of the inner values are displaying for some reason. Also, I only have 4 results but there are 6 rows. I tried many different tweaks after going through documentation and similar questions, to no avail.
Here is the html
Course Catalog
<table class="jsonTable">
<thead>
<tr>
<th id="year">Year</th>
<th id="term">Term</th>
<th id="code">Code</th>
<th id="title">Title</th>
</tr>
</thead>
<tbody>
{{#each this}}
<tr>
<td>{{year}}</td>
<td>{{term}}</td>
<td>{{code}}</td>
<td>{{title}}</td>
</tr>
{{/each}}
</tbody>
</table>
main.js
$(".jsonTable").hide();
$("#catalog").on("click", function(){
console.log('catalog button clicked');
$.get('/catalog', function(data){
console.log(data);
$("#catalog").hide();
$(".jsonTable").show();
});
});
});
Console
DevTools
I'm trying to use angular-smart-table for grid in my new AngularJS app. According to the document, to sort a column, I should use the st-sort directive like bellow:
<th st-sort="firstName">first name</th>
<th st-sort="lastName">last name</th>
However, I'm trying to re-use the piece of code for not only one table, so I don't know the table field names in advance until the run-time. I'm doing something like bellow:
<script type="text/ng-template" id="content1">
<div ng-repeat="table in $ctrl.tables">
<h2>{{table._tableName}}</h2>
<table st-table="table._data" class="table table-striped">
<tr>
<th ng-repeat="fieldName in table._fieldNames" st-sort="{{fieldName}}">{{fieldName}}</th>
</tr>
<tr ng-repeat="data in table._data">
<td ng-repeat="fieldName in table._fieldNames">{{$ctrl.formatCell(table, data, fieldName)}}</td>
</tr>
</table>
</div>
</script>
And this cannot work (cannot sort, other functions OK). I tried bellow it does not work, seems the st-sort has to be in the <th> tag.
<th ng-repeat="fieldName in table._fieldNames"><span st-sort="{{fieldName}}">{{fieldName}}</span></th>
And bellow does not work as well:
<tr>
<span ng-repeat="fieldName in table._fieldNames">
<th st-sort="{{fieldName}}">{{fieldName}}</th>
</span>
</tr>
Today I tried to develop a directive and use it in the comment by setting restrict to "M" to solve the above. Then I got a new problem: I'm using UI-Router in this app and I cannot get the table contents in my directive, because UI-Router states have isolated scopes and it only supports controllers but does not support directives. The author may think supporting directives is not necessary (yes in most cases, but this kind of assumptions are always dangerous).
I'm Trying two possible ways: 1., put the field names to the session/local storage for sharing as a work-around; 2., abandon UI-Router. Appreciate anyone providing a better solution.
Hi my Project is working on Django and Python and some AngularJS. What I want to achieve is I've a dynamic history table, which increases when the data populates. I want to add a simple css to this table, like for every even number of rows I need to add a black background to the row and grey for odd number of rows.My table looks like this. How can I achieve that? Any idea guys? Thanks in advance.
<table class="table table-bordered">
{%verbatim %}
<tr align="center">
<td><b>Modified By</b></td>
<td><b>Modified Date</b></td>
<td><b>Field</b></td>
<td><b>Old Value</b></td>
<td><b>New Value</b></td>
</tr>
<tr align="center" ng-repeat="(k,v) in final_data.histories" onMouseOver="this.style.background='#d2d2d2'; this.style.color='#000000'"
onMouseOut="this.style.background='#f5f5f5'; this.style.color='#000000'" ng-cloak>
<td>{{ v.username }}</td>
<td>{{ v.date_created }}</td>
<td>{{ v.field_name }}</td>
<td>{{ v.old_value }}</td>
<td>{{ v.new_value }}</td>
</tr>
You can do this using ngClassEven and ngClassOdd directives built into angular, to be used with ng-repeat. For example:
<tr ng-repeat="(k,v) in final_data.histories" ng-class-even="'my-even-class'" ng-class-odd="'my-odd-class'">
Then you simply need to add the my-even-class and my-odd-class classes to your css, and style as you want.
Update: If you have more complex requirements for styling (eg, not just based on whether a row is odd or even, you can apply conditional classes based on any logic you want using ng-class. Say you wanted to style every row whose item has a field myField that was greater than 5.
<div ng-class="{'my-class' : v.myField > 5}"></div>
This will only put the my-class class on the items that adhere to the condition, and then can be styled as you wish.
I am new to Angular JS and I am trying to use ng-repeat to generate multiple row in my table, and in each row there should be a button to trigger a function with different parameter
<div ng-controller="testing">
<table>
<thead>
<tr>
<th>col 1</th>
<th>col 2</th>
<th>button</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items">
<td>{{ item.prop1 }}</td>
<td>{{ item.prop2 }}</td>
<td><button ng-click="myFunction(item.id)">Trigger Function</button></td>
</tr>
</tody>
</table>
</div>
This of course doesn't work, as the ng-repeat creates its own scope, while myFunction is defined in the parent scope (i.e. the testing controller).
However, all I can find in Google result is the reason of not working, but lacks a way to fix the problem. How should I correct my code so that the ng-click works? Is there a way to define myFunction inside ng-repeat scope or is there a way to tell I want the function in the parent scope?
Change the ng-click to following
<button ng-click="testing.myFunction(item.id)">
Improve ng-repeat performance – using track by with ng-repeat
Pass $index to track your ng-repeat and which ng-click is being cliked
<tr ng-repeat="item in items track by $index">
<td>{{ item.prop1 }}</td>
<td>{{ item.prop2 }}</td>
<td><button ng-click="myFunction($index,item.id)">Trigger Function</button></td>
</tr>
For Reference
Probably one of the very first things you learned doing with Angular was how to use ngRepeat. It’s so easy and simple, you gotta love it. Here’s an example:
<ul class="tasks">
<li ng-repeat="task in tasks" ng-class="{done: task.done}">
{{task.id}}: {{task.title}}
</li>
</ul>
The problem
Now say you have a button above that list to refresh it.
The obvious implementation for this refresh would be something along these lines in your controller:
$scope.tasks = newTasksFromTheServer;
This is a trivial piece of code, but it would cause ngRepeat to remove all li elements of existing tasks and create them again, which might be expensive (e.g. we have a lot of them or each li’s template is complex). That means a lot of DOM operations.
Why would Angular do this? Behind the scenes ngRepeat adds a $$hashKey property to each task to keep track of it. If you replace the original tasks with new tasks objects from the server, even if those are in fact totally identical to your original tasks, they won’t have the $$hashKey property and so ngRepeat won’t know they represent the same elements.
track by to the rescue
In Angular 1.2 a new addition was made to the syntax of ngRepeat: the amazingly awesome track by clause. It allows you to specify your own key for ngRepeat to identify objects by, instead of just generating unique IDs.
This means that you can change the above to be ng-repeat="task in tasks track by task.id" and since the ID would be the same in both your original tasks and the updated ones from the server – ngRepeat will know not to recreate the DOM elements and reuse them. Boom.
you can also use ‘track by $index’ if your data source has duplicate data
//Below code will throw Error: dupes Duplicate Key in Repeater
<div ng-repeat="value in [4, 4]"></div>
//Below code will work perfectly fine
<div ng-repeat="value in [4, 4] track by $index"></div>
I can do this in Angular.js:
<tr ng-repeat="cust in customers">
<td>
{{ cust.name }}
</td>
</tr>
Which would iterate through all the customers by putting each in a <tr> of its own.
But what if I wanted two customers in one <tr>? How would I accomplish that?
I normally do that by messing around with indexes and modulus values, but I'm not sure how to do that here.
It turns out this can be done without any custom filters or changing the format of your data, though it does require some extra markup. I thought this woudn't be possible at first as you can't use a span or anything similar within the table for your ng-repeat. This answer however, points out that you can use a tbody.
So it's just a case of using the ng-if directive (which renders html if the expression is true), the $index variable (provided by ng-repeat) and the $even variable (which is also provided by ng-repeat and is true when $index is even
I've created a demo in this Plunker
<div ng-controller="MainCtrl">
<table>
<tbody ng-repeat="cust in customers">
<tr ng-if="$even">
<td>{{customers[$index].text}}</td>
<td>{{customers[$index+1].text}}</td>
</tr>
</tbody>
</table>
</div>
This would of course only work if you have two columns, what if you have more? Well you can also put a full expression into ng-if rather than just a variable. So you can use modulus values like this:
<tbody ng-repeat="cust in customers">
<tr ng-if="($index % 3) == 0">
<td>{{customers[$index].text}}</td>
<td>{{customers[$index+1].text}}</td>
<td>{{customers[$index+2].text}}</td>
</tr>
</tbody>