How to skip $index in ng-repeat - angularjs

Consider the following:
<div ng-repeat='quest in quests'>
<div ng-switch on="quest.ui.type">
<div ng-switch-when="ms-select-single" >
<div ms-select-single quest='quest'
quest-num='{{(true)?numInc():return}}'></div>
</div>
<div ng-switch-when="ms-select-multy">
<div ms-select-multy quest='quest'
quest-num='{{(true)?numInc():return}}'></div>
</div>
<div ng-switch-when="ms-date">
<div ms-date quest='quest'
quest-num='{{(true)?numInc():return}}'>{{questNo}}</div>
</div>
<div ng-switch-when="ms-text">
<div ms-text quest='quest'
quest-num='{{(true)?numInc():return}}'>{{questNo}}</div>
</div>
<div ng-switch-when="ms-textarea">
<div ms-textarea quest='quest'
quest-num='{{(true)?numInc():return}}'>{{questNo}}</div>
</div>
<div ng-switch-when="ms-number">
<div ms-number quest='quest'
quest-num='{{(true)?numInc():return}}'>{{questNo}}</div>
</div>
<div ng-switch-when="ms-html">
<div ms-html quest='quest'></div>
</div>
</div>
</div>
What should be my true statement in the quest-num='{{(true)?numInc():return}}'>?
What i want to achieve is an increment a model value conditionaly when the statement is true, if it's true all the time the program breaks, what should be my true statement here?
numInc returns a ++ of a num value in the model, initialized first at 0, and when it hits the function it increments, but because i have ng-switch it increments too many times, that's why i need the true/false statement, i think...

I'm not sure I understood your question but if you wanted something like this
Label Actual $index value
Question 1 0
1
Question 2 2
Question 3 3
etc...
Then we can use a directive. Here's a quick sketch
var app = angular.module('app', []);
app.controller('MainController', function($scope){
$scope.arr = [{name:'John', phone:'555-1276'},
{name:'Mary', phone:'800-BIG-MARY'},
{name:'Mike', phone:'555-4321', countMe:false},
{name:'Adam', phone:'555-5678'},
{name:'Julie', phone:'555-8765'},
{name:'Juliette', phone:'555-5678', countMe:false}]
});
app.directive('conditionalNumberDirective', function(){
var counter = 0;
return {
restrict: 'A',
link: function(scope, el, attr) {
// config what is item and what is coutMe via attrs here
if(scope.$index === 0) {
counter = 1;
}
scope.counter = counter;
if(angular.isDefined(scope.item) && angular.isDefined(scope.item.countMe) && !scope.item.countMe) {
scope.counter = null;
}else {
counter++
}
}
}
});
Html would look something like
<div ng-controller="MainController">
<input type="text" ng-model="search"/>
<div ng-repeat="item in arr | filter:search" conditional-number-directive>
Index:{{$index}} {{item}} - Label:{{counter}}
</div>
</div>

Instead of $index use a ng-model variable. You could try something like this also(ternary):
{{ true ? true : false }}
while assigning the value.

Related

How to pass a variable from a directive to a controller

How to show or hide a div in a Html, related to a controller, using the variable from a directive.
To show or hide div in html use ng-show:
<div ng-show="myValue"></div>
when myValue is true div element will be visible ,if false then it will hide.
you have to declare that my value in controller that is true or false such as scope.myValue=true;
More details here: Angularjs ng-show
Now passing variable from directive to controller this will help Easiest way to pass an AngularJS scope variable from directive to controller?
In below code I have showed ng-show and ng-hide using both examples using HTML to handle and controller to handle.
In first ng-hide hide the dhaarani name. In controller used to show the dhaarani name using
$scope.hai = false;
inside timeout function
$timeout(countUp, 2000);
Try below code.
var showApp = angular.module('showApp', [])
.controller('mainController', function($scope,$timeout) {
// set the default value of our number
$scope.myNumber = 0;
// function to evaluate if a number is even
$scope.isEven = function(value) {
if (value % 2 == 0)
return true;
else
return false;
};
$scope.timeInMs = 0;
$scope.hai = true;
$scope.welcome = true;
var countUp = function() {
$scope.hai = false;
alert("sgf");
}
$timeout(countUp, 2000);
});
.profilename{color:red;}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container" ng-app="showApp" ng-controller="mainController">
<div class="page-header text-center">
<h1>ngShow and ngHide: Functions</h1>
</div>
<!-- ANIMALS =========================================================== -->
<div class="row">
<div class="col-xs-4">
<form>
<div class="form-group">
<label>Type a Number</label>
<input type="text" class="form-control" ng-model="myNumber">
</div>
</form>
</div>
<div class="col-xs-8 jumbotron text-center">
<!-- show if our function evaluates to false -->
<div ng-show="isEven(myNumber)">
<h2>The number is even.</h2>
</div>
<!-- show if our function evaluates to false -->
<div ng-show="!isEven(myNumber)">
<h2>The number is odd.</h2>
</div>
</div>
</div>
<div class="page-header text-center">
<h1>ngShow and ngHide: using controller</h1>
</div>
<p ng-show="welcome">welcome</p>
<p ng-hide="hai" class="profilename">Dhaarani</p>
</div>

Directive is Not Called when the ng-repeat is finished

I want to call the directive when my ng-repeat is finished. I use two controllers with same name. My problem is that when I call the function of controller the function changes the value of the list. And base on that list ng-repeat is work. When ng-repeat is end directive is called that called the END function. But ng-repeat not work as well as directive also not called.
my HTML code is here
> <body ng-app="modules" >
<div class="container" >
<div class="row" ng-controller="mainctl">
<div class="col-sm-1">
<a href="#" ng-click="divide(1)" ><h3>1*1</h3></a>
</div>
<div class="col-sm-1">
<h3>2*2</h3>
</div>
<div class="col-sm-1">
<h3>3*3</h3>
</div>
<div class="col-sm-1">
<h3>4*4</h3>
</div>
<div/>
<div ng-controller="mainctl">
<div ng-repeat="rows in cells" > <!-- repeat fot rows -->
<div class="row">
<div ng-repeat="cols in cells" repeat-end="onEnd()"> <!-- repeat for colums -->
<div id="Div_{{rows}}{{cols}}" class="col-sm-2 rcorners2">
<center><h1>{{rows}}{{cols}}</h1></center>
<div id="divPictureBoxPlayback{{rows}}{{cols}}" class="pictureboxPlayback'"
ad-drop="true"
ad-drop-end="onDrop($data, $dragElement, $dropElement, $event);" >
<div id="divHeaderPictureBoxPlayback{{rows}}{{cols}}" class="panel panel-default margin-b-0 text-center pictureboxHeader row"
ng-hide="StartPlayerPlayback{{rows}}{{cols}}" >
<div class="">
<span class="col-lg-3 col-xs-3 col-md-3 text-left">{{cameraNamePlayback00}}</span>
<span class="col-lg-9 col-xs-9 col-md-9 text-right pad-0">
<button class="margin-r-10 btn btn-xs" ng-click="StopStreaming('{{rows}}{{cols}}')"><i class="fa fa-close"></i></button>
</span>
</div>
</div>
<div id="divStreamingAreaPlayback{{rows}}{{cols}}" class="video-cointainer text-center row" ng-hide="StartPlayerPlayback{{rows}}{{cols}}"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
here is my controller
app.controller('mainctl', function ($scope,$timeout) {
$scope.cells =["0"];
//Scopes.store('mainctl', $scope);
$scope.divide = function (ar)
{
$scope.value = ar;
$scope.cells = [];
for (var i = 0; i < ar; i++)
{
$scope.cells.push(i + "");
}
}
$scope.divide1=function()
{
for(var i=0;i<$scope.value;i++)
{
for(var j=0;j<$scope.value ;j++)
{
$scope.index=""+i+j;
$("#divPictureBoxPlayback" + $scope.index).attr('class', 'picturebox pictureboxPlayback' + i + j);
$("#divPictureBoxPlayback" + index).show();
}
}
}
$scope.onEnd = function(){
$timeout(function(){
alert('all done');
$scope.divide1();
}, 1);
}
});
here is my directive
app.directive("repeatEnd", function($timeout){
return {
restrict: "A",
link: function (scope, element, attrs) {
if (scope.$last) {
alert("last element ");
scope.$eval(attrs.repeatEnd);
}
}
};
})
It seems you are missing timeout. You will need timeout in your code in directive:
app.directive("repeatEnd", function ($timeout) {
return {
restrict: "A",
link: function (scope, element, attrs) {
if (scope.$last) {
$timeout(function () {
alert("last element ");
scope.$eval(attrs.repeatEnd);
});
}
}
};
})
$timeout will ensure it is executed only when ng-repeat finishes its rendering. The reason for using $timeout over setTimeout is because it will call $apply internally.

How to show another scope value in view corresponding to other value?

I am newbie to angular. I have two scope variables i.e,$scope.jsonData and $scope.dbdatas. I want to show value from $scope.jsonData corresponding to $scope.dbdatas.name. Please check my code. I have mentioned my desire output in the code.
View:
<div ng-app="myApp">
<div ng-controller="TestCtrl">
<div class="col-md-4 col-lg-4 col-xs-6" style="padding: 10px" ng-repeat="dbdata in dbdatas">
<div>
{{dbdata.name}} : <span class="list_text">{{dbdata.value}}</span>
<!--something like {{dbdata.name}} : <span show-value class="list_text">{{dbdata.value}}</span>-->
</div>
</div>
</div>
var app = angular.module('myApp', []);
app.controller('TestCtrl',function($scope){
$scope.jsonData=[{"_id":"56f90a9a51ec8f20e786a9e7","name":"Eleget","options":[{"key":"Y","value":"Once"},{"key":"M","value":"More than once"}]},{"_id":"56f90a9a51fs8f20e786a9e7","name":"MoliRet","options":[{"key":"L","value":"Let"},{"key":"R","value":"Ret"}]}];
$scope.dbdatas=[{name:'MoliRet',value:'L'},{name:'MoliRet',value:'R'},{name:'Eleget',value:'M'}];
});
/*app.directive('showValue',function(){
return{
restrict:'A',
link:function(scope,ele,attr){
}
}
});*/
Current Output
MoliRet : L
MoliRet : R
Eleget : M
Desire Output
MoliRet: Let
MoliRet: Ret
Eleget: More than once
Working Fiddle
HTML:
<div ng-app="myApp">
<div ng-controller="TestCtrl">
<div class="col-md-4 col-lg-4 col-xs-6" style="padding: 10px" ng-repeat="item in jsonData">
<div ng-repeat='option in item.options'>
<div ng-show="isInArray(option.key)">
{{item.name}}: {{option.value}}
</div>
</div>
</div>
</div>
</div>
JavaScript:
var app = angular.module('myApp', []);
app.controller('TestCtrl',function($scope){
$scope.isInArray = function(key){
var returnValue = false;
for(var i=0;i<$scope.dbdatas.length;i++){
if($scope.dbdatas[i].value==key){
returnValue = true;
break;
}
}
return returnValue
}
$scope.jsonData=[{"_id":"56f90a9a51ec8f20e786a9e7","name":"Eleget","options":[{"key":"Y","value":"Once"},{"key":"M","value":"More than once"}]},{"_id":"56f90a9a51fs8f20e786a9e7","name":"MoliRet","options":[{"key":"L","value":"Let"},{"key":"R","value":"Ret"}]}];
$scope.dbdatas=[{name:'MoliRet',value:'L'},{name:'MoliRet',value:'R'},{name:'Eleget',value:'M'}];
});
Output:
Eleget: More than once
MoliRet: Let
MoliRet: Ret
Hope that solve your problem.
You can use angular.ForEach to match data from both scope variables and push the data to an array $scope. Please take a look at the solution below.
<div ng-app="myApp">
<div ng-controller="TestCtrl">
<div class="col-md-4 col-lg-4 col-xs-6" style="padding: 10px" ng-repeat="dbdata in dbdatas">
<div>
{{dbdata.name}} : <span class="list_text">{{dbdata.value}}</span>
</div>
</div>
<div ng-repeat="expect1 in expectations">{{expect1.name}}: {{expect1.value}}</div>
</div>
</div>
$scope.dbdatas=[{name:'MoliRet',value:'L'},{name:'MoliRet',value:'R'},{name:'Eleget',value:'M'}];
$scope.expectations= [];
angular.forEach($scope.dbdatas,function(value1){
angular.forEach($scope.jsonData,function(value2){
if(value1.name == value2.name){
angular.forEach(value2.options,function(value3){
if(value3.key == value1.value){
$scope.expectations.push({
"name" : value2.name,
"value": value3.value});
}
});
}
});
});
Expected output will be
MoliRet: Let
MoliRet: Ret
Eleget: More than once
I would suggest you have to store a unique options table in one json and use angular custom service filter to handle the relative key 'look at the plunker'. you can use this custom filter in any controller and view.
Here is custom filter
app.filter('myFilter', ['$filter', function ($filter) {
return function (data, param) {
var output = $filter('filter')(data, {key:param},true);
return (param && output.length) ? output[0].value : '';
};
}]);
Here is a working plunker
.Hope that help.

Accessing $scope of another controller - ngDialog in AngularJS

I'm instantiating ngDialog like below;
ngDialog.open({
template: 'mod-details',
className: "ngDialog-theme-large",
showClose: false,
closeByDocument: false,
closeByEscape: false,
controller: ['$scope', function($scope) {
// controller logic
$scope.isValid = true;
$scope.orderItem = orderItem;
$scope.countSelection = function() {
var count = 0;
angular.forEach($scope.modifier.menu_modifier_items, function(item){
count += item.selected ? 1 : 0;
});
console.log(item);
return count;
}
}]
});
I then use $scope.orderItem with ng-repeat like below;
<div ng-repeat="modifier in orderItem.menu_modifier_groups">
<div class="menu--modifiers-group" modifier="modifier">
<div class="group-title" ng-class="{'group-hasError': !isValid}">
<div class="title-s ng-binding" ng-bind="modifier.name"></div>
<div class="clearfix"></div>
<span class="text-muted ptop5" ng-if="modifier.instruction" ng-bind="modifier.instruction"></span>
</div>
<div class="group-items" ng-if="modifier.max_selection_points > 1 || (modifier.max_selection_points == 1 && modifier.min_selection_points == 0)">
<div ng-repeat="item in modifier.menu_modifier_items" class="modifier-item multiple">
<label for="<%modifier.id + '_' + item.id%>" ng-click="modifierClicked(item)">
<input id="<%modifier.id + '_' + item.id%>"
class="checkbox-branded"
type="checkbox"
name="<%item.name%>"
ng-model="item.selected"
ng-class="{'not-available': !item.available}"
title="<%item.name%>"
value="<%item.id%>"
ng-disabled="!item.selected && countSelection() == modifier.max_selection_points"
ng-click="modifierClicked(item)"
ng-change="modifierSelected(item, false)">
<span class="item-name">
<span ng-bind="item.name"></span>
<span ng-bind="priceDelta(modifier, item)"></span>
</span>
</label>
</div>
</div>
</div>
</div>
</div>
I'm not able to access modifier in ng-repeat="modifier in orderItem.menu_modifier_groups" or modifier.menu_modifier_items in ng-repeat="item in modifier.menu_modifier_items" in my countSelection function
I've attached a screenshot of ng-inspector.
$scope.modifier is never created into your controller. Your countSelection function can't know which item of the array is being selected this way. One way you could do, is to pass a reference of the array to your function when calling it. Like this:
countSelection(modifier.menu_modifier_items);
And, on the controller:
$scope.countSelection = function(selection) {
var count = 0;
angular.forEach(selection, function(item){
count += item.selected ? 1 : 0;
console.log(item);
});
return count;
}

Looping though an object in Angular and using the key inside a ng-show

i am creating a simple Angular.js tabbing box which changes the box that is active accoring to a value 'tab' that is used inside ng-show on the elements.
This is working fine, however, at the moment I am writing all the HTML statically and I would rather cut down my code into a simple ng-repeat loop to loop through all the divs.
This is easy enough in PHP as I would use a foreach loop and use the key to generate the tab number, I just can't seem to do this in Angular. Here is my code at the moment:
<div id="services-box-nav">
<ul>
<li>Rewards</li>
<li>Community</li>
<li>Partners</li>
<li>Jobs</li>
<li>Volunteering</li>
<li>Feedback</li>
<li>Gallery</li>
</ul>
</div>
<div id="services-content-boxes">
<div ng-show="tab == 1">
<div class="row">
<div class="col-md-12">
<h3>{{serviceBoxes.rewards.title}}</h3>
</div>
</div>
<div class="row">
<div class="col-md-5">
{{serviceBoxes.rewards.text}}
</div>
<div class="col-md-7">
</div>
</div>
</div>
<div ng-show="tab == 2">dwd</div>
<div ng-show="tab == 3">d</div>
<div ng-show="tab == 4">df</div>
<div ng-show="tab == 5">gr</div>
<div ng-show="tab == 6">r</div>
<div ng-show="tab == 7">rg</div>
</div>
controller('servicesController', function($scope, $location, joomlaService) {
$scope.serviceBoxes = {};
joomlaService.getArticleDetails(21).then(function(articleReturnData) {
$scope.serviceBoxes.rewards = articleReturnData;
});
joomlaService.getArticleDetails(22).then(function(articleReturnData) {
$scope.serviceBoxes.community = articleReturnData;
});
joomlaService.getArticleDetails(23).then(function(articleReturnData) {
$scope.serviceBoxes.partners = articleReturnData;
});
joomlaService.getArticleDetails(24).then(function(articleReturnData) {
$scope.serviceBoxes.jobs = articleReturnData;
});
joomlaService.getArticleDetails(25).then(function(articleReturnData) {
$scope.serviceBoxes.volunteering = articleReturnData;
});
joomlaService.getArticleDetails(26).then(function(articleReturnData) {
$scope.serviceBoxes.feedback = articleReturnData;
});
joomlaService.getArticleDetails(27).then(function(articleReturnData) {
$scope.serviceBoxes.gallery = articleReturnData;
});
});
What I want to do is loop through the serviceBoxes object and dynamically create the ng-show condition (tab == i) using the key, which should increment each time (1, 2, 3, 4, etc). I don't know how I go about this using Angular. It would cut down my code considerably so feel it is necessary.
Can anyone point out how this is done?
Thanks
You can use angular-ui bootstrap Tabset directive.
<tabset>
<tab ng-repeat="serviceBox in serviceBoxes" heading="{{serviceBox.title}}" active="serviceBox.active">
{{serviceBox.text}}
</tab>
</tabset>
Thus your view is clean and tidy.
And your controller will look like:
controller('servicesController', function($scope, $location, joomlaService) {
$scope.serviceBoxes = [];
joomlaService.getArticleDetails(21).then(function(articleReturnData) {
$scope.serviceBoxes.push(articleReturnData);
});
joomlaService.getArticleDetails(22).then(function(articleReturnData) {
$scope.serviceBoxes.push(articleReturnData);
});
joomlaService.getArticleDetails(23).then(function(articleReturnData) {
$scope.serviceBoxes.push(articleReturnData);
});
joomlaService.getArticleDetails(24).then(function(articleReturnData) {
$scope.serviceBoxes.push(articleReturnData);
});
joomlaService.getArticleDetails(25).then(function(articleReturnData) {
$scope.serviceBoxes.push(articleReturnData);
});
joomlaService.getArticleDetails(26).then(function(articleReturnData) {
$scope.serviceBoxes.push(articleReturnData);
});
joomlaService.getArticleDetails(27).then(function(articleReturnData) {
$scope.serviceBoxes.push(articleReturnData);
});
});
<ul>
<li ng-repeat="serviceBox in serviceBoxes">{{serviceBox.title}}</li>
</ul>
<div ng-repeat="serviceBox in serviceBoxes" ng-show="tab == {{selectedIndex}}">{{serviceBox.contents}}</div>
In your controller:
$scope.selectedIndex = 0; // Default selected index, use -1 for no selection
$scope.itemClicked = function ($index) {
$scope.selectedIndex = $index;
};
The ng-repeat directive loops through every element and makes a copy of the html element it's placed inside of. If there at 10 items to look through, you will have 10 html elements. It also you references to the index of the current element via $index.
ng-click will call the function on itemClicked(), passing in the current index through the $index reference that ng-repeat supplied. In our function we're using that parameter to set our $scope.selected to it.
I have tried creating something similar. Try below code
I have hardcoded mapTab array.You can populate myTab using the corresponding values from $scope
In controller-
$scope.tab;
$scope.mapTab=[{},{"1": "dwd"},{"2":"d"},{"3":"dwd"},{"4":"df"},{"5":"gr"},{"6":"r"},{"7":"rg"}];
In html--
<div ng-repeat="(key,val) in mapTab">
<div ng-repeat="prop in val">
<div ng-show="tab==key">{{prop}}</div>
</div>
</div>
</div>
Demo--http://jsfiddle.net/RahulB007/HB7LU/9348/

Resources