angular ng-repeat with some logic - javascript

I have this object
recipe = {
name : $scope.name,
ingredients : $scope.ingredients
}
I save ingredients in two different ways, that are
ingredients1 = [{ingredient : 'berry'}, {ingredient : 'honey'}]
ingredients2 = ['berry', 'honey'];
In ng-repeat I need to past ingredient depending on the condition;
//ingredients1
<li ng-repeat="ingr in recipe.ingredients track by $index">
<b>{{ingr}}</b>
</li>
//ingredients2
<li ng-repeat="ingr in recipe.ingredients track by $index">
<b>{{ingr.ingredients}}</b>
</li>
Can I make 1 ng-repeat for this two situations, with some conditional statements like if or else?

If ingr.ingredient is defined then bind it, else bind ingr, i.e.:
{{!!ingr.ingredient ? ingr.ingredient : ingr}}
Try with this code:
angular.module('myApp', [])
.controller('MyCtrl', function($scope, $http) {
var myScope = this;
myScope.ingredients = [{
ingredient: 'berry'
}, {
ingredient: 'honey'
}, 'berry', 'honey'];
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<ul ng-app="myApp" ng-controller="MyCtrl as c">
<li ng-repeat="ingr in c.ingredients track by $index">
<b>{{!!ingr.ingredient ? ingr.ingredient : ingr}}</b>
</li>
</ul>

If you know that you'll never have a third variation you could do
<li ng-repeat="ingr in recipe.ingredients track by $index">
{{ingr.ingredient || ingr}}
</li>
However, this is not that maintainable. I think it might be cleaner to delegate this logic to a helper function.
<li ng-repeat="ingr in getIngredients(recipe.ingredients)">
{{ingr}}
</li>
function getIngredients(ingredients) {
// Logic to flatten your mix of objects and strings
}
This would allow you to add/change the model of recipe ingredients while also creating logic that can be separately unit tested

There are couple of ways, all are worked listed down here.
Here is a Plunkr
angular.module('myApp',[])
.controller('myCtrl', function($scope){
$scope.array1 = [{ingredient : 'berry'}, {ingredient : 'honey'}]
$scope.array2 = ['berry', 'honey'];
$scope.array3 = [{ingredient : 'berry'}, {ingredient : 'honey'}, 'berry', 'honey'];
});
<h1>array 1</h1>
<li ng-repeat="ingr in array1">
<b>{{ ingr.ingredient || ingr }}</b>
</li>
<h1>array 2</h1>
<li ng-repeat="ingr in array2">
<b>{{ ingr.ingredient ? ingr.ingredient : ingr }}</b>
</li>
<h1>array 3</h1>
<li ng-repeat="ingr in array3">
<b>{{ ingr.ingredient || ingr }}</b>
</li>
<li ng-repeat="ingr in array3">
<b>{{ ingr.ingredient ? ingr.ingredient : ingr }}</b>
</li>

Related

ng-repeat on array based on length of second array

I am trying to iterate over an array using ng-repeat to display in a list. The number of records to display should be equal to the length of a second array.
<ul>
<li ng-repeat="item in firstArray"></li>
</ul>
var firstArray = ["a","b","c","d","e","f"]
var secondArray = ["x","y","z"]
The expected result for the above example :
var output = ["a","b","c"]
Since the length of secondArray is 3, the number of li elements would be 3 with the first three values from firstArray.
Should i use filter? I am using angularjs.
Thanks
The simplest solution is to use limitTo
<ul>
<li ng-repeat="item in firstArray | limitTo:secondArray.length">{{item}}</li>
</ul>
http://plnkr.co/edit/LWh1uqNPxTy09u3MP677?p=preview
<ul>
<li ng-repeat="item in firstArray" ng-if=" $index < secondArray.length "></li>
</ul>
Use the above code, it will work
You can use AngularJs filter limitTo in ng-repeat. Refer to the below example:
At angular application side:
var app = angular.module('sampleapp', [])
app.controller('samplecontrol', function ($scope) {
$scope.firstArray = ["a","b","c","d","e","f"]
$scope.secondArray = ["x","y","z"]
});
In your view:
<ul>
<li ng-repeat="item in firstArray | limitTo:secondArray.length">{{item}}</li>
</ul>
Maybe you should use $index to test if it has to be displayed :
<ul >
<li ng-repeat="item in firstArray" ng-if="$index < secondArray.length()" > </li>
</ul>
Just loop over your second array and access the items of the first array using firstArray[$index].
angular.module('myApp', [])
.controller('myCtrl', function ($scope) {
$scope.firstArray = ["a","b","c","d","e","f"];
$scope.secondArray = ["x","y","z"];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<ul>
<li ng-repeat="i in secondArray">
{{firstArray[$index]}}
</li>
</ul>
</div>
</div>

Pagination shown even though there is no data in angular

Here is my code:
Buttons:
<li ><a data-ng-click="Data1 = true;Data2 = false; search.status = ''" href="">ALL PROJECTS</a></li>
<li ><a data-ng-click="Data2 = true;Data1 = false" href="">NOTIFICATIONS</a></li>
Populated data on click of button:
<ul>
<li ng-show="Data1" dir-paginate="wd in workOrdersList | filter: search.status | filter: search.name | itemsPerPage: 10">
<a href="">
<h4>{{wd.name}}</h4>
</a>
<p>Status: {{wd.status}}</p>
</li>
<li ng-show="Data2">
<div ng-show="!notificationDataDashord.length">
<span>No Notifications</span>
</div>
</li>
</ul>
<dir-pagination-controls auto-hide="true"></dir-pagination-controls>
Inside the controller:
$scope.Data1 = true;
$scope.Data2 = false;
I am using pagination directive from this link:
https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
Its a problem with the dirpagination that it doesnt update the collections after you load the data again.
See
https://github.com/michaelbromley/angularUtils/issues/208
https://github.com/michaelbromley/angularUtils/issues/137
As a work around obviously
<dir-pagination-controls ng-show="Data1" auto-hide="true"></dir-pagination-controls>

Make newest item on top in To Do List using Angular

I have a problem with my todo list. I want when I input a new item, it appears on top of list items, not below the list items. I have put track by -$index but it doesn't work
index.html snippet
<ul class="unstyled">
<li ng-repeat="todo in todos track by -$index">
<input type="checkbox" ng-model="todo.done">
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
controller.js snippet
app.controller('TodoListController', ['$scope', function($scope) {
$scope.todos = [];
$scope.addTodo = function() {
$scope.todos.push({text:$scope.todoText, done:false});
$scope.todoText = '';
};
Are there any solution for this ?
Use unshift() to prepend the items to your array instead of push() and remove your track by -$index
Javascript
app.controller('TodoListController', ['$scope', function($scope) {
$scope.todos = [];
$scope.addTodo = function() {
$scope.todos.unshift({text:$scope.todoText, done:false});
$scope.todoText = '';
};
HTML
<ul class="unstyled">
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done">
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
The solution from #nipeco works fine but it changes the logic for presentation purposes which personally I wouldn't recommend.
I think it's best to push and use the filter orderBy+reverse to have the desired output.
<li ng-repeat="todo in todos | orderBy:'-$index':reverse">
Hope it helps!

Select item from list and send it back to server using Javascript AngularJS

I have a list of items. I want to select them by clicking. Selected item will be sent to server. At a time only one item can be selected. So, for this I need a variable where I can store the item. Please no jQuery. I am looking for simple Javascript AngularJS. Here is my html. After selecting one item, it will automatically go to another list, which I kept in ng-if=false. Suppose, I click on item1 then it will show the list of list1, list2 and list3. Now, let's select list2. Now item1 and list2 will both go to server.
<div ng-if="true"class="items">
<ul ng-if="true">
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
<ul ng-if="false">
<li>list1</li>
<li>list2</li>
<li>list3</li>
</ul>
</div>
In my fiddle, if I select one date then it should list of dates, which is given ng-if='false'
fiddle link :- http://jsfiddle.net/abhijitloco/k6jso1u3/
Look
function AppController($scope) {
$scope.selectedItem = [];
$scope.clickItem = function(item) {
$scope.selectedItem.push(item);
}
};
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="AppController">
{{selectedItem}}
<div class="items">
<ul ng-if="true">
<li ng-click="clickItem('Item1');">Item1</li>
<li ng-click="clickItem('Item2');">Item2</li>
<li ng-click="clickItem('Item3');">Item3</li>
</ul>
<ul ng-repeat="obj in selectedItem">
<li>{{obj}}</li>
</ul>
</div>
</div>
<div class="items">
<ul ng-if="!selectedItem" ng-model="selectedItem">
<li ng-click="selectedItem = item1">Item1</li>
<li ng-click="selectedItem = item2">Item2</li>
<li ng-click="selectedItem = item3">Item3</li>
</ul>
<ul ng-if="selectedItem" ng-model="selectedList">
<li ng-click="selectedList = list1">list1</li>
<li ng-click="selectedList = list2">list2</li>
<li ng-click="selectedList = list3">list3</li>
</ul>
</div>
You have selected item in selectedItem model and selected list in selectedList model.
Assuming that yours lists and items are dynamic I would propose something like the following:
constroller:
$scope.lists = [list1, list2, list2...]
$scope.items = [item1, item2, item3...]
$scope.selectItem = function(index){
$scope.selectedItem = $scope.items[index];
};
$scope.sentToServer = function(index){
$scope.lists[index].push($scope.selectedItem);
//send $scope.lists[index] and $scope.selectedItem;
};
view:
<div ng-if="true" class="items">
<ul ng-if="true">
<li ng-click="selectItem($index)" ng-repeat="item in items>{{item}</li>
</ul>
<ul ng-if="selectedItem">
<li ng-click="sendToServer($index)" ng-repeat="lists in lists>{{'list' + $index}</li>
</ul>
</div>
<div ng-if="true"class="items">
<ul ng-repeat='entry in list1'>
<li ng-click='clickMe(entry.name)'>{{entry.name}}</li>
</ul>
<ul ng-repeat='entry1 in list2' ng-if="secondList">
<li ng-click='sendToserver(entry1.name)'>{{entry1.name}}</li>
</ul>
</div>
contorller.js
$scope.optionsSelected = {};
$scope.clickMe = function(text){
$scope.optionsSelected['first'] = text;
$scope.secondList = true; // show second list
// you can initialize second list here OR reset values before it is sent to sever
}
$scope.sendToserver = function(text){
$scope.optionsSelected['second'] =text;
$scope.textSelected = $scope.optionsSelected;
// $scope.textSelected contains both options you just selected.
}
You can do this with couple of ngClick and ngIf directives. For example:
$scope.showType = 1;
$scope.selected = {};
$scope.selectDate = function(date) {
$scope.showType = 2;
$scope.selected.date = date;
};
$scope.selectTime = function(time) {
$scope.selected.time = time;
$http.post('date/selected', $scope.selected); // post wherever you need
};
where in HTML you would have
<ul class="datepicker text-center" ng-if="showType === 1">
<li ng-click="selectDate(date)" ng-repeat="date in dateValues">{{date | date:'EEE dd'}}</li>
</ul>
<ul class="datepicker text-center" ng-if="showType == 2">
<li ng-click="selectTime(time)" ng-repeat="time in timeValues">{{time}}</li>
</ul>
And here is your code updated:
Demo: http://plnkr.co/edit/SjxbyfboJlkLnOeDBhdn?p=preview

Angular JS filter not equals

Seems like a very basic question but I can't get the syntax right..
<li class="list-group-item" ng-repeat="question in newSection.Questions | filter:Id != '-1'; " ng-mouseenter="hover = true" ng-mouseleave="hover = false">
<div href="#" editable-text="question.Text">{{question.Text}}</div>
</li>
All I want is to show all the questions where id is NOT -1.
What am I doing wrong. Thanks!
The syntax is just a little off, try:
<li class="list-group-item"
ng-repeat="question in newSection.Questions | filter:{ Id: '!-1'}"
ng-mouseenter="hover = true" ng-mouseleave="hover = false">
<div href="#" editable-text="question.Text">{{question.Text}}</div>
</li>
See a little JSFiddle: http://jsfiddle.net/U3pVM/3845/
Edit:
Example with variables:
<script> var invalidId = '-1'; </script>
<li class="list-group-item"
ng-repeat="question in newSection.Questions | filter:{ Id: '!' + invalidId}"
ng-mouseenter="hover = true" ng-mouseleave="hover = false">
<div href="#" editable-text="question.Text">{{question.Text}}</div>
</li>
Although #Michael Rose answer works for this case, i don't think it will if you try to filter not equal some object/variable
In that case you could use:
JS:
filterId = -1
HTML:
<li ng-repeat="question in newSection.Questions | filter: !{ Id: filterId}">
</li>
An even more nested case:
JS:
someQuestion = {
someObject: {
Id: 1
}
}
newSection.Questions = [someQuestion]
HTML
<li ng-repeat="question in newSection.Questions | filter: !{someObject : {Id: -1} }">
</li>

Categories