I have an angular app with one controller and one view, in my view I have a navigation bar with four options, the thing is that I cant create more html files, I need to work all in the index.html file that is under my app folder, in that file I have three tables where I bind some data coming from a WS that I call in three differente functions in my controller file, for example like this:
<table class="table table-bordered" ng-if="topTable === 'topCategory'">
<tbody>
<tr ng-repeat="d in data">
<td ng-bind = "d.Name">
<td ng-bind = "d.Email">
</tr>
</table>
<table class="table table-bordered" ng-if="topTable === 'topBrand'">
<tbody>
<tr ng-repeat="d in data">
<td ng-bind = "d.Name">
<td ng-bind = "d.Email">
</tr>
</table>
I hide the firs two and depending on the radio button selection that I have other tables appears.
My issue is that as I mentioned before, my navigation bar has four options where I have three more tables for each option, so I saw something about directives but Im new to angular and I want to know how to render all the html that I have in my current view without losing functionality and allowing the app to render the correct data depending on the selected option of the nav bar.
I really need help on this.
Thanks
Related
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.
I'm trying to integrate NgTable with angularjs 1.5 in a component-based architecture (so, no old-style controllers).
The NgTable controls (filter, icons for sorting) appear, but they don't seem to work at all, so they don't filter and don't sort.
Here's my code
--- activity-list-module.js ---
angular.module('activityList', ['ngTable']);
--- activity-list-component.js ---
(function(){
'use strict';
angular.
module('activityList').
component('activityList', {
templateUrl: "app/activity-list/activity-list.html",
controller: ['NgTableParams', function (NgTableParams) {
var self=this;
self.activitiesForm=[{id:0,description:"att0"},{id:1,description:"att1"},{id:2,description:"att2"}];
self.tableParams = new NgTableParams({}, { dataset: self.activitiesForm});
}]
});
})();
--- activity.list.html ----
<div style="margin:20pt">
<h3>Manage Activities</h3>
<div style="margin:20pt">
<h3>Manage Activities</h3>
<div class="row" style="margin-left:20pt" >
<table id="myViewTable" ng-table="$ctrl.tableParams" class="table" show-filter="true" class="table actTable" style="width:95%;table-layout: fixed;" >
<tbody>
<tr ng-repeat="projectActivity in $ctrl.activitiesForm track by projectActivity.id">
<td data-title="'Id'">{{projectActivity.id}}</td>
<td data-title="'description'" filter="{ description: 'text'}" sortable="'description'">{{projectActivity.description}}</td>
</tr>
</tbody>
</table>
</div>
</div>
Of course the component is called using the tag <activity-list></activity-list> in another page.
I'm working with AngularJs 1.5.8 and ng-table 3.0.1.
I'm doing something wrong or there is an incompatibility between AngularJs >= 1.5 and ng-table ?
Here is the plnkr
PS In the last case, how can I do ? Is smarttable compatible with AngularJs 1.5 ?
After raised an issue in ng-table GIT repo i got a working example from the creator of ng-table and i could have a look.
The point is in the use of controller variables, instead of a $data variable generated by ng-table.
So, in the case of the 'new style' component the issue is solved changing
<tr ng-repeat="projectActivity in $ctrl.activitiesForm track by projectActivity.id">
with
<tr ng-repeat="projectActivity in $data track by projectActivity.id">
In the case of the "old Style" controller it's solved changing
<tr ng-repeat="user in vm.data">
with
<tr ng-repeat="user in $data">
I don't like a lot this solution, because it add a kind of global, but it works.
EDIT
it works also using
$ctrl.tableParams.data (for Component Example) and vm.tableParams.data (for the Controller Example) which let me feel much better about.
I've built a report which uses a set of nested ng-repeat directives to create what can be an enormous table. It works well to build the table, but after that, the scrolling performance is affected greatly - I assume this is due to what must be the large number of watches created by the ng-repeats.
The report only has to be built once and then is static. I don't need to watch the data continually.
I have two questions:
A) is there anyway to see a list of all the variables Angular is currently watching?
EDIT: This post was a great help in learning how to benchmark
B) Is there anyway to tell Angular to stop all of the watches it is doing? I've seen lots of posts about canceling watches which one sets up oneself, but that these are native directives, I'm not sure how I'd tap into them.
My preference would be to have a variable that I can say "if truthy, then do all watches, if not, then do not watch" or a function to just say "start watches" and "stop watches".
I have set up a very nice DOM watching service which can tell when all of the ng-repeats have executed, so I can know when I want to stop watching.
This is the table itself. Aside from tk-ng-repeat-completed, the other "tk-" attributes are just used for data and aren't actually directives.
<div class="table-responsive">
<table tk-sticky-column id="records" class="table table-striped table-hover table-condensed">
<!-- tbody[n] -->
<tbody class="dataset" ng-repeat="dataset in report.data track by $index" tk-ng-repeat-completed>
<!-- row[0] -->
<tr class="headline">
<!-- header[0] label -->
<th class="headline" style="background-color:#042E34;">
<div style="width:200px;"><h4>{{report.labels.y[$index]}}</h4></div>
</th>
<!-- header[n] label -->
<th ng-repeat="x_label in report.labels.x" tk-ng-repeat-completed
class="datapoint date"
tk-raw-data="{{x_label}}">
<em><small>{{x_label}}</small></em></th>
<!-- header[last] space for addition #todo remove this, add during calculations -->
<th class="date"></th>
</tr>
<!-- row[n] -->
<tr ng-repeat="(key, datapoints) in dataset" tk-metric-key="{{key}}">
<!-- column[0] label -->
<td tk-metric-key="{{key}}"
tk-calc="{{report.labels.data[key].calc}}"
class="rowdesc begin">{{key}}</td>
<!-- column[n] data -->
<td ng-repeat="datapoint in datapoints track by $index" tk-ng-repeat-completed
ypos="{{$parent.$parent.$parent.$index}}" xpos="{{$index}}" tk-metric-key="{{key}}"
class="datapoint"
tk-raw-data="{{datapoint}}">
{{datapoint}}</td>
</tr>
</tbody>
</table>
</div>
I'd recommend checking out the single-bind syntax they introduced in 1.3, if you're on a version greater than or equal to that one. It works really well and is very simple to implement. Here's an example:
normal syntax, which creates a watcher for each variable:
<div ng-repeat="foo in vm.bar">
{{foo}}
</div>
single-bind syntax, with no watcher on the nested variable inside the repeat:
<div ng-repeat="foo in vm.bar">
{{::foo}}
</div>
edit:
I forgot to mention that if your data isn't going to change at all after it gets populated the first time (e.g. from a $http.get), you can also just use the single-bind syntax on the top level ng-repeat:
<div ng-repeat="foo in ::vm.bar">
{{::foo}}
</div>
I have situation when i need to repeat multiple tbody in one table, what im trying to do is to make every tbody directive and i want its template to append to table, but when im put the directive inside the table tag its put his content outside the table.
the cart draw directive:
return {
restrict : 'AE',
templateUrl: 'client/cart/views/cart-draw.html',
scope : {},
replace: true,
controller : controller
}
the tpl:
<tbody ng-repeat="draw in CartService.items.draws track by $index">
<tr>
<td>
//some content
</td>
</tr>
</tbody>
the html:
<table class="table">
<cart-draw></cart-draw>
</table>
here is the plunker, if you inspect element you will see the tbody is out of the table:
http://plnkr.co/edit/9wEGFE5K0w0ayp6qo8Lx?p=preview
That is happening because the <table> tag doesn't recognize your custom <cart-draw> element as a valid child.
I would modify like so: http://plnkr.co/edit/u88N76h5dvLAvR3C1kRs?p=preview
index.html
<table><tbody cart-draw></tbody></table>
cart-draw.html
<tbody ng-repeat="body in bodies">
<tr>
<td>
{{body}}
</td>
</tr>
</tbody>
app.js
$scope.bodies = ["hello1", "hello2", "hello3"];
This is a long pending issue in Angular's Github repo.
https://github.com/angular/angular.js/issues/1459
I also stumbled upon to this problem once (with SVG). It happens because before rendering the directive, the template is cross verified with HTML DTD and alone doesn't make sense (without tag) and so it doesn't work. Same applies to <tr> and <li>
There are many solutions which uses ng-transclude and link functions to wrap it in respective parent tag and then use it.
This is actually a known & strange issue when it comes to directives & <table>'s.
I believe it actually comes in as invalid HTML at first, causing it somehow appear outside of your <table> tag.
Try making cart-draw an attribute of a <tbody>:
<table>
<tbody cart-draw></tbody>
</table>
plunker Example
This will make it work as intended.
I wanted to have the functionality of rearranging rows in a table (sorting rows using drag and drop).
And the index of the row arrangement should also change in the model.
How can I do something similar to this : http://jsfiddle.net/tzYbU/1162/
using Angular Directive?
I am generating table as :
<table id="sort" class="table table-striped table-bordered">
<thead>
<tr>
<th class="header-color-green"></th>
<th ng-repeat="titles in Rules.Titles">{{titles.title}}</th>
</tr>
</thead>
<tbody ng-repeat="rule in Rules.data">
<tr>
<td class="center"><span>{{rule.ruleSeq}}</span></td>
<td ng-repeat="data in rule.ruleData">{{statusArr[data.value]}}</td>
</tr>
</tbody>
</table>
I did it. See my code below.
HTML
<div ng:controller="controller">
<table style="width:auto;" class="table table-bordered">
<thead>
<tr>
<th>Index</th>
<th>Count</th>
</tr>
</thead>
<tbody ui:sortable ng:model="list">
<tr ng:repeat="item in list" class="item" style="cursor: move;">
<td>{{$index}}</td>
<td>{{item}}</td>
</tr>
</tbody>{{list}}
<hr>
</div>
Directive (JS)
var myapp = angular.module('myapp', ['ui']);
myapp.controller('controller', function ($scope) {
$scope.list = ["one", "two", "thre", "four", "five", "six"];
});
angular.bootstrap(document, ['myapp']);
There is another library: RubaXa/Sortable: https://github.com/RubaXa/Sortable
It is for modern browsers and without jQuery dependency. Included is a angular directive. I'm going to check it out now.
You get good touch support additionally.
AngularJS was not really built for the manipulation of DOM elements, rather to extend the HTML of a page.
See this question and this Wikipedia entry.
For DOM manipulation, jQuery/mootools/etc will suite you just fine (hint: the example in your jsFiddle link).
You could probably use AngularJS to keep track of the ordering of your elements to update your model. I'm not sure how to do this using directives, but the following code may be useful
var MyController = function($scope, $http) {
$scope.rules = [...];
...
}
var updateRules = function(rule, position) {
//We need the scope
var scope = angular.element($(/*controller_element*/)).scope(); //controller_element would be the element with ng-controller='MyController'
//Update scope.rules
}
Then when you reorder the list, simply call updateRules() with the changed rule and its new position in the model.
Anyone else who wants something like this but not understanding the accepted answer. Here is a directive UI.Sortable for AngularJS that allows you to sort an array/ table rows with drag & drop.
Requirements
JQuery v3.1+ (for jQuery v1.x & v2.x use v0.14.x versions)
JQueryUI v1.12+
AngularJS v1.2+
Usage
Load the script file: sortable.js in your application: (you can find this sortable.js from here
<script type="text/javascript" src="modules/directives/sortable/src/sortable.js"></script>
make sure you have included JQuery, AngularJs and JQueryUI js files in
order before this sortable file
Add the sortable module as a dependency to your application module:
var myAppModule = angular.module('MyApp', ['ui.sortable'])
Apply the directive to your form elements:
<ul ui-sortable ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
Developing Notes:
ng-model is required, so that the directive knows which model to update.
ui-sortable element should contain only one ng-repeat
Filters that manipulate the model (like filter, orderBy, limitTo,...) should be applied in the controller instead of the ng-repeat
3rd point is very Important as it took almost an hour to understand
why my sorting was not working?? It was because of orderBy in html
and that was resetting the sorting again.
For more understanding you can check the detail here.
If I understand you correctly, you want to be able to sort the rows? If so, use UI-Sortable: GitHub
Demo: codepen.io/thgreasi/pen/jlkhr
Along with RubaXa/Sortable there is one more angularjs library avilable that is angular-ui-tree. Along with drag and drop we can arrange elements in a tree structure and we can add and delete elements (nodes)
Please see the this link for examples
http://angular-ui-tree.github.io/angular-ui-tree/#/basic-example .
Please see this for github
https://github.com/angular-ui-tree/angular-ui-tree.