I have a list of orders that I sort based on status key. Then I display it using ng-repeat in bars. I can click Accept button to move one order from submitted to accepted. The question is: How do I refresh the bar displaying accepted orders?
HTML
<div class="bar" ng-controller="AdminCtrl">
<li ng-repeat="order in submitted">
<div >
<p >{{order.name}} </p>
<p>{{order.total}}</p>
<button class="btn" ng-click="acceptOrder(order)">Akceptuj</button>
</div>
</li>
</div>
<div class="bar" ng-controller="AdminCtrl" >
<li ng-repeat="order in delivery">
<div >
<p >{{order.name}} </p>
<p>{{order.total}}</p>
<button class="btn" ng-click="addOrderToDeliveryQueue(order)">Dodaj do kolejki dostawy</button>
</div>
</li>
</div>
</div>
JS
$scope.submitted = [];
$scope.accepted = [];
$scope.delivery = [];
angular.forEach($scope.orders, function(value, key) {
if (value.status == 'submitted')
$scope.submitted.push(value);
if (value.status == 'accepted')
$scope.accepted.push(value);
if (value.status == 'delivery')
$scope.delivery.push(value);
});
$scope.acceptOrder = function(order) {
var index = $scope.submitted.indexOf(order);
order.status = 'accepted';
$scope.accepted.push(order);
$scope.submitted.splice(index, 1);
AngularJS handles refreshing ng-repeat directives automatically when it sees a change in the collection. You are not seeing this behavior because you are actually creating multiple independent instances of your AdminCtrl controller. Each of your divs has this: ng-controller="AdminCtrl". This creates a new instance of the AdminCtrl scoped to that div. What you really want is one instance of that AdminCtrl. You can achieve this by moving the ng-controller directive to the outermost container element.
<div ng-controller="AdminCtrl">
<div class="bar">
<li ng-repeat="order in submitted">
// your markup
</li>
</div>
<div class="bar">
<li ng-repeat="order in accepted">
// your markup
</li>
</div>
</div>
// etc.
I'm new in angular and I reeding A.Freeman's book "Pro Angular JS".
So I stuck in one of examples trying to understand why filter in ng-repeat is triggered.
Here is the code:
<body ng-controller="sportsStoreCtrl">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">SPORTS STORE</a>
</div>
<div class="panel panel-default row" ng-controller="productListCtrl">
<div class="col-xs-3">
<a ng-click="selectCategory()" class="btn btn-block btn-default btn-lg">Home</a>
<a ng-repeat="item in data.products | orderBy:'category' | unique:'category'" ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg">
{{item}}
</a>
</div>
<div class="col-xs-8">
<div class="well" ng-repeat="item in data.products | filter:categoryFilterFn">
<h3>
<strong>{{item.name}}</strong>
<span class="pull-right label label-primary">
{{item.price | currency}}
</span>
</h3>
<span class="lead">{{item.description}}</span>
</div>
</div>
</div>
</body>
and
angular.module("sportsStore")
.controller("productListCtrl", function ($scope, $filter) {
var selectedCategory = null;
$scope.selectCategory = function (newCategory) {
selectedCategory = newCategory;
}
$scope.categoryFilterFn = function (product) {
return selectedCategory == null ||
product.category == selectedCategory;
}
});
categoryFilterFn is one that confuses me. Why it's invoking when I press catefory buttons (with selectCategory() method on ng-click) since I never call categoryFilterFn explicitly?
Answering you question - because of $digest. You don't have call categoryFilterFn directly. Your selectedCategory has changed which is used in categoryFilterFn and categoryFilterFn is bound to scope.
Not sure how I can describe it correctly but here my explanation.
There are two "independent" parts :
The repeat iterate over an array of items.
If you select an category via ng-click function you set the new category in the scope.
Here kicks the filter function in, witch ties it up.
It is triggered because a new category is selected ($digest) and "reordering" the array (like map function in plain Javascript) and the angular magic (ng-repeat) displays only items with this category.
And that's the reason why I love angular so much 🤓
I have a condition and it is only on selecting an image among the optional images the next button needs to get enabled and also next should not get enabled on last outer select.
The problem here is on selecting the first image, the button is getting enabled and the scope is assigning the value to false and it is not getting true for the second iteration of images. How can I fix this issue?
<div class="col-xs-6 col-md-10 col-lg-7">
<div ng-repeat="outer in outers track by $index">
<div ng-if="outer_index== $index">
<div ng-bind="::outer.label"></div>
<ul class="list-group">
<li class="cursorPointer" ng-repeat="inner in outer.inners | orderBy: 'id'" ng-class="{'selected': getSelectedClass($parent.$index, $index)}" class="deselected">
<div class="col-xs-6">
<div class="img">
<img ng-src="data:image/png;base64,{{inner.base64Icon}}" alt="{{inner.description}}" title="{{inner.description}}"
ng-click="process()">
<div class="desc" ng-bind="inner.description"></div></div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div><button type="button" class="btn btn-info" ng-disabled="outer_index == outers.length -1 || disableNext" ng-click="getNext()">Next</button></div>
In JS code, to activate the button only if,
$scope.disableNext=true;
$scope.process = function() {
$scope.disableNext=false;
}
$scope.getNext = function (){
$scope.outer_index = $scope.outer_index + 1;
$scope.datas = $scope.outers[$scope.outer_index];
}
NOTE: I tried
ng-click="process();disableNext=false;" for this condition won't work within ng-repeat.
Just set the disableNext to true after selecting next and it works!
$scope.getNext = function() {
$scope.disableNext=true;
$scope.outer_index = $scope.outer_index + 1;
$scope.datas = $scope.outers[$scope.outer_index];
}
Most of the answers I've found are for repeating the entire object, and that works for me without problem. What I need is to display the objects of an element in an array. Here is my controller:
var app = angular.module('QLoad', []);
app.controller('loadCtrl', function($scope) {
$scope.question=[
{Id:'1', qText:'What\'s your Gender?',aCollection:[
{text:'Male',
icon:'fa fa-male fa-5x'},
{text:'Female',
icon:"fa fa-female fa-5x"}
]
},
{Id:'2', qText:'What kind of Pain do you have?',aCollection:[
{text:'Burning',
icon:'fa fa-fire fa-5x'},
{text:'Stinging',
icon:"fa-bee.png"}
]
}];
});
As I mentioned, I could easily do two nested ng-repeats and display everything, but I only need to display the answers for each individual question. That's why I have the following two views I've tried, but it neither works:
<h1>{{question[0].qText}}</h1>
<div ng-repeat="q in question">
<div ng-repeat="answer in q.aCollection" class="content">
<div class=button>
<i class="{{q[0].answer.icon}}" aria-hidden="true"></i>
{{q[0].answer.text}}
</div>
</div></div>
Nor does this work:
<h1>{{question[0].qText}}</h1>
<div ng-repeat="answer in question[0].aCollection" class="content">
<div class=button>
<i class="{{answer.icon}}" aria-hidden="true"></i>
{{answer.text}}
</div>
</div></div>
And this is where I'm stuck. I can't display a single question object and its nested array. Thank you for your help.
You can use [limitTo][1] filter to achieve that.
<div ng-repeat="q in question | limitTo:1">
<div ng-repeat="answer in q.aCollection" class="content">
<div class=button>
<i class="{{answer.icon}}" aria-hidden="true"></i>
{{answer.text}}
</div>
</div></div>
You can define an index which will be incremented with the ng-click.
Template
<h1>{{question[questionTrackIndex].qText}}</h1>
<div ng-repeat="answer in question[questionTrackIndex].aCollection" class="content">
<div class=button>
<i class="{{answer.icon}}" aria-hidden="true"></i>
{{answer.text}}
</div>
</div>
<div class="btn btn-warning" ng-if="questionTrackIndex != 0" ng-click="previousQuestion()">Previous</div>
<div class="btn btn-warning" ng-if="question.length - 1 > questionTrackIndex" ng-click="nextQuestion()">Next</div>
Controller
$scope.questionTrackIndex = 0;
$scope.question=[
{Id:'1', qText:'What\'s your Gender?',aCollection:[
{text:'Male',
icon:'fa fa-male fa-5x'},
{text:'Female',
icon:"fa fa-female fa-5x"}
]
},
{Id:'2', qText:'What kind of Pain do you have?',aCollection:[
{text:'Burning',
icon:'fa fa-fire fa-5x'},
{text:'Stinging',
icon:"fa-bee.png"}
]
},
{Id:'3', qText:'Question no 3',aCollection:[
{text:'Answer1',
icon:'fa fa-fire fa-5x'},
{text:'Answer2',
icon:"fa-bee.png"}
]
}
];
$scope.nextQuestion = function() {
$scope.questionTrackIndex++;
}
$scope.previousQuestion = function() {
$scope.questionTrackIndex--;
}
The variable $scope.questionTrackIndex has been used to scroll through the questions. I have added two buttons next and previous to scroll through the questions. With clicking next button, $scope.questionTrackIndex has been incremented and with clicking previous button, $scope.questionTrackIndex has been decremented.
See this PLUNKER
One of solution maybe is
<div ng-repeat="q in question">
<div ng-click="a($index)">{{q.qText}}</div>
</div>
<h1>{{answ.text}}</h1>
<div ng-repeat="answer in answ.answerList" class="content">
<div class=button>
<i class="{{answer.icon}}" aria-hidden="true"></i>
{{answer.text}}
</div>
and your controller look like
$scope.answ = {};
$scope.answ.text = $scope.question[0].qText
$scope.answ.answerList = $scope.question[0].aCollection;
$scope.a = function(index){
$scope.answ.text = $scope.question[index].qText
$scope.answ.answerList = $scope.question[index].aCollection;
}
Example you can see on link
I have 3 elements, which shows by conditional. on click of them using the 'ng-class' I am showing or hiding the element.
here is the HTML :
<div class="userOptions">
<div class="row designOption" ng-class="{'active':proDesign}">
<span ng-click="categories('proDesign')" class="icon iconD">D</span>
<span class="info infoD">Design</span>
</div>
<div class="row suplyOption" ng-class="{'active':Supply}">
<span ng-click="categories('proSupply')" class="icon iconS">S</span>
<span class="info infoS">Supply</span>
</div>
<div class="row constOption" ng-class="{'active':Construct}">
<span ng-click="categories('proConstruct')" class="icon iconC">C</span>
<span class="info infoC">Construction</span>
</div>
</div>
But using the scope function I am not able to shuffle the class name active. here is my try:
$scope.proDesign = false;
$scope.proConstruct = false;
$scope.proSupply = false;
$scope.categories = function (categ) {
$scope.proDesign = false; //all are false.
$scope.proConstruct = false;
$scope.proSupply = false;
$scope[categ] = !$scope[categ]; //became true
}
But this is not working. if so, what is the correct way to do this?