I have this HTML:
<table>
<tr ng-repeat-start="client in clients" ng-controller="ClientCtrl">
<td ng-click="toggleExpand()">
Expand
</td>
<!-- some html -->
</tr>
<tr ng-show="isExpanded" ng-repeat-end>
<!-- some html -->
</tr>
</table>
And this JS:
angular.module('app').controller('ClientCtrl', function($scope){
$scope.isExpanded= false;
$scope.toggleExpand = function(){
$scope.isExpanded = !$scope.isExpanded;
}
});
For each repeated element, I want the same instance of ClientCtrl to apply to both ng-repeat-start and ng-repeat-end, so that isExpanded can be toggled from inside of ng-repeat-start and be accessible via ng-repeat-end.
Is it possible?
EDIT:
I'm not looking for workarounds to make the toggle work, what I really want is to be able to share a scope across ng-repeat-start and ng-repeat-end, and the functionality of the toggle is just an example.
Yes it is. You will need to use the $index of the item in order to be able to toggle each individually.
HTML:
<table>
<tr ng-repeat-start="client in clients" ng-controller="ClientCtrl">
<td ng-click="toggleExpand($index)">
Expand
</td>
<!-- some html -->
</tr>
<tr ng-show="isExpanded($index)" ng-repeat-end>
<!-- some html -->
</tr>
</table>
And update the toggleExpand function accordingly.
Figured out a way do do it:
<table>
<tr ng-repeat-start="client in clients" ng-controller="ClientCtrl">
<td ng-click="vm.toggleExpand()">
Expand
</td>
<!-- some html -->
</tr>
<tr ng-show="vm.isExpanded" ng-repeat-end ng-controller="ClientEndCtrl">
<!-- some html -->
</tr>
</table>
angular.module('app').controller('ClientCtrl', function($scope){
$scope.vm = {
isExpanded: false,
toggleExpand: function(){
$scope.vm.isExpanded = !$scope.vm.isExpanded;
}
}
}).controller('ClientEndCtrl', function($scope){
// vm is a shared view model across ng-repeat-start and ng-repeat-end
$scope.vm = $scope.$$prevSibling.vm;
});
Related
myCtrl.Data.summary.account
if i print above model i get the output like below
["1","2","3","4","5"]
i want to use ng-repeat on this value, how to achive this?
I tried following code snippet using ng-repeat but it's not printing anything
<td ng-repeat="data in myCtrl.Data.summary.account">
<tr>{{data}}</tr>
</td>
What mistake i made here? can anyone please point out this issue. How to fix this?
it is ng-repeat not ng-repet
<td ng-repeat="data in myCtrl.Data.summary.account">
<tr>{{data}}</tr>
</td>
1) Use ng-repeat instead of ng-repet
2) If you are using controllerAs syntax check if myCtrl is correct controller name in controllerAs value
3) If you are using $scope then you should create $scope.myCtrl.Data.summary.account in controller
You should place the value in the columns and repeat for the rows. Your code should be in this format:
<tr ng-repeat="data in myCtrl.Data.summary.account">
<td>{{data}}</td>
</tr>
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.arr = ["1","2","3","4","5"]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<table>
<tr>
<td ng-repeat="data in arr">
<table>
<tr>
<td >{{data}}
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
cant use directly <tr>inside <td> . you need to create a table and add it there
<td ng-repeat="data in myCtrl.Data.summary.account">
<table>
<tr>
<td>{{data}}
</td>
</tr>
</table>
</td>
i am having this inside my controller method.
var employee = [{name:"ankur",dept:"IT",company:"wipro",under:[{name1:"ashish"},{name1:"akash"},{name1:"tyagi"},{name1:"mogra"}]}];
$scope.employee = employee;
and this inside html page.
<table>
<tr ng-repeat="emp in employee">
<td>{{emp.name}}</td>
<td>{{emp.dept}}</td>
<td>{{emp.company}}</td>
<td ng-repeat="(key , value) in emp.under">
a<td>{{key}}</td>
b<td>{{value}}</td>
</td>
</tr>
</table>
However, first ng-repeat is working fine, but it shows nothing at place of nested ng-repeat.
Your ng-repeat is fine, The problem is with the td inside another td, to do that you can do like this instead :
Fiddle
<div ng-app='app' ng-controller='mainCtrl'>
<table>
<tr ng-repeat="emp in employee">
<td>{{emp.name}}</td>
<td>{{emp.dept}}</td>
<td>{{emp.company}}</td>
<td ng-repeat="(key , value) in emp.under">{{value.name1}}
<table>
<tr>
a<td>{{key}}</td>
b<td>{{value.name1}}</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
If you just want to check if your ng-repeat is working, remove the <td>'s and check like this :
<td ng-repeat="(key , value) in emp.under">
a{{key}}
b{{value}}
</td>
When i am using ng-if with a flag and list contains some values:
<tr ng-if="flag" ng-repeat="x in list1">
{{"print a"}}
<!-- do something -->
</tr>
<tr ng-if="!flag" ng-repeat="x in list2">
{{"print b"}}
<!-- do something -->
</tr>
It is printing both a and b irrespective of flag.It should only print a and b based on flag value?
Here you go..
var app = angular.module('myApp',[])
.controller('myCtrl',function($scope){
$scope.flag = true;
$scope.list1 = [10,20,30,40,50];
$scope.list2 = [10,20,30,40,50];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<table ng-app="myApp" ng-controller="myCtrl">
<tr ng-if="flag" ng-repeat="x in list1">
<td>
{{"print a"}}
</td>
</tr>
<tr ng-if="!flag" ng-repeat="x in list2">
<td>
{{"print b"}}
</td>
</tr>
</table>
So, it does work.
I'm not sure how to do this in angular, after coming from jquery.
I have a table:
<div class="col-xs-10">
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
</thead>
<tbody ng-repeat="val in data">
<tr>
<td>val.Time</td>
<td>val.Distance</td>
<td ng-click="callmethod()"><img src="delete"></td>
</tr>
</tbody>
</table>
</div>
Essentially I want the callmethod() to know which row is being clicked so that I can make a update in the model in my controller. What is the right way to do this?
You can use the $index property:
callmethod($index)
Then on your controller you would do something like:
function callmethod(index) {
var foo = $scope.data[index];
}
Change that ng-click to this:
<td ng-click="callmethod(val)"><img src="delete"></td>
You'll get the whole val object when that method gets called.
I've just started using AngularJS and wanted to create a custom template directive for creating "in-place" editable tables. The idea would be to have something like:
<tr ng-repeat="customer in model.customers">
<ng-template ng-hide="customer === model.selectedCustomer"> <!-- display template-->
<td>{{customer.name}}</td>
</ng-template>
<ng-template ng-show="customer === model.selectedCustomer"> <!-- edit template -->
<td><input type="text" ng-model="customer.name"/></td>
</ng-template>
</tr>
It could then also be extended to specify a templateUrl e.g. <ng-template template-url="foo.html"></ng-template>
When I apply the ng-show directive to my custom directive it does not work. Here's the code for my directive:
var demo = angular.module("demo", [])
.directive("ng-template", function() {
return {
restrict: "E",
replace: true,
transclude: true
}
});
and HTML (http://jsfiddle.net/benfosterdev/ASXyy/):
<div ng-app="demo">
<table>
<tr ng-repeat="name in ['jane', 'john', 'frank']">
<ng-template ng-show="name !== 'frank'">
<td>{{name}}</td>
</ng-template>
</tr>
</table>
</div>
Furthermore, when I look at the generated HTML my custom directive doesn't even appear in the table:
<div ng-app="demo" class="ng-scope">
<ng-template ng-show="name !== 'frank'" class="">
</ng-template>
<table>
<tbody>
...
</tbody>
</table>
</div>
Essentially I'm trying to avoid writing code like this (setting the ng-show directive on every <td> element):
<table>
<tr ng-repeat="customer in customers">
<ng-template>
<td ng-hide="isSelected">{{customer.name}}</td>
<td ng-hide="isSelected">{{customer.age}}</td>
<td ng-hide="isSelected"><button ng-click="edit(customer)"</td>
<td ng-show="isSelected"><input type="text" ng-model="customer.name"/></td>
<td ng-show="isSelected"><input type="text" ng-model="customer.age"/></td>
<td ng-show="isSelected"><button ng-click="save(customer)"</td>
</ng-template>
</tr>
</table>
A couple of things occur to me when I look at your code.
ng-include offers very similar functionality to your proposal for extending ng-template. If you're going to load a view based on the state of the underlying model then I think this would be the way to go.
If you're not going to be loading the template from a separate view file, why not just use ng-show (or ng-if / ng-switch, which I prefer in most cases) on your td element?
Here is some example code using ng-include:
<table>
<thead>
<th>One</th>
<th>Two</th>
<th>Three</th>
<th></th>
</thead>
<tbody>
<tr ng-repeat="item in items" ng-include="getTemplate(item)"></tr>
</tbody>
</table>
Here is the full JSFiddle: http://jsfiddle.net/qQR6j/2.
Use ng-repeat-start and ng-repeat-end to specify the two alternative <tr> tags.
<div ng-app="demo">
<table ng-controller="Ctrl">
<tr ng-repeat-start="name in ['jane', 'john', 'frank']" ng-hide="isSelected(name)">
<td>{{name}} <button ng-click="select(name)">edit</button></td>
</tr>
<tr ng-repeat-end ng-show="isSelected(name)">
<td>{{name}}!</td>
</tr>
</table>
</div>
With this javascript
var demo = angular.module("demo", []);
demo.controller("Ctrl",
function Ctrl($scope) {
var selected;
$scope.isSelected = function(name) {
return selected === name;
};
$scope.select = function(name) {
selected = name;
};
});
Live example: http://jsfiddle.net/6FtjG/1/
Your browser renders the 'ng-template' outside of the table because its not a valid child of tr. Even if you have set replace to true, the directive needs to be rendered before it can be replaced.
You can see it is because of the table, because this does work:
<div>
<div ng-repeat="name in ['jane', 'john', 'frank']">
<ng-template ng-show="name !== 'frank'">
<div >{{name}}</div>
</ng-template>
</div>
</div>
see: Fiddle
This is something your browser does so you cannot avoid it.