How to correct this redundancy in an array? - javascript

I'm building an app in ionic, and I need to pass items into another array, but when I pass the same item again it's considered the same item - really - but I need that to not happen. I need them to be considered different or or at least be considered different. Each item(is an object) of array have a var "qntt"(quantity) and when this bug happen, instead put the same item in array, plus one in this var. OBS: I'm using ng-repeat="item in items track by $index" in html.
<ion-view title="Order">
<ion-content overflow-scroll="true" padding="true" style="background: url(img/background1.jpg) no-repeat center;" class="has-header" ng-controller="pedidoCtrl">
<button class="button button-dark button-small button-block" ng-click="showDelete = !showDelete">Remover</button>
<ion-list show-delete="showDelete">
<ion-item class="item-thumbnail-left item-remove-animate" ng-repeat="item in items track by $index">
<ion-delete-button class="ion-minus-circled" ng-click="deleteItem(item)"></ion-delete-button>
<img src="{{item.img}}">
<h2>{{item.nome}}</h2>
<div class="row">
<div class="col col-60">
<h2>R{{item.subtotal | currency}}</h2>
</div>
<div class="col col-15">
<button class="button button-clear button-assertive button-small icon ion-minus" ng-click="subQtt(item)"></button>
</div>
<div class="col col-10">
<h2>{{item.qtt}}</h2>
</div>
<div class="col col-15">
<button class="button button-icon-right button-clear button-assertive button-small icon ion-plus" ng-click="addQtt(item)"></button>
</div>
</div>
</ion-item>
</ion-list>
<button style="text-align:right;" class="button button-assertive button-block icon-left ion-cash">R{{total | currency}}</button>
<div style="margin-right:-20px;">
<button style="left:-10px;" class="button button-dark button-large button-full icon ion-android-cart">Order</button>
</div>
</ion-content>
.controller('orderCtrl', function($scope, productService) {
$scope.items = null;
$scope.items = productService.getProducts();
$scope.deleteItem = function(item){
$scope.items.splice($scope.items.indexOf(item), 1);
};
$scope.$watchCollection('items', function(array) {
if (array) {
$scope.total = array.reduce(function(total,item) {
return total + item.subtotal;
},0);
}
$scope.addQtt = function(item){
item.qtt = item.qtt + 1;
item.subtotal = item.price * item.qtt;
$scope.total = array.reduce(function(total,item) {
return total + item.subtotal;
},0);
};
$scope.subQtt = function(item){
if(item.qtt > 1)
{
item.qtt--;
item.subtotal = item.price * item.qtt;
}
else
{
$scope.items.splice($scope.items.indexOf(item), 1);
}
$scope.total = array.reduce(function(total,item) {
return total + item.subtotal;
},0);
};
});
})
.service('productService', [function(){
var productList = [];
var addProduct = function(product) {
productList.push(product);
};
var getProducts = function(){
return productsList;
};
return {
addProduct: addProduct,
getProducts: getProducts,
};
}]);

That's because you are not calling the service method addProduto() within your controller. Try calling produtoService.addProduto() within the $scope.addQnt() method as below and it should work:
$scope.addQnt = function(item){
item.qntd = item.qntd + 1;
item.subtotal = item.preco * item.qntd;
$scope.total = array.reduce(function(total,item) {
return total + item.subtotal;
},0);
// Add this line to retain your addition in service
produtoService.addProduto(item);
// Get updated list of products
$scope.items = productoService.getProdutos();
// Alternatively use '$scope.items.push(item)'
};
Also, you need to refresh your $scope.items by triggering a call to productoService.getProdutos(), though you can do it directly by pushing in $scope.items.push(item)

Related

AngularJS / AngularFire - Pass Objects with ng-click

I have a modal (bootstrap) where I load Objects from the Firebase Database. Now I added a ng-Click to "select" an Object.
I want to select 8 Object and "collect" them. After I collected these 8 Objects, I want to pass them to another ng-Click. When I click on the second ng-Click these 8 (selected) Objects are pushed to the Database.
Do you have any idea how to archive that? Thank you!
This is my modal:
<div class="col-md-12">
<ul class="list-group">
<li ng-repeat="team in teams" class="list-group-item">{{ team.allUserTeamName + " - " + team.allUserTeam }}
<i class="fa fa-plus-circle" aria-hidden="true" ng-init="item.isClicked = false" ng-click="selectMembers(team); item.isClicked =!item.isClicked" ng-class="{clicked : item.isClicked}"></i>
</li>
</ul>
</div>
<div class="modal-footer">
<div class="col-md-12">
<div class="row pad-team-selection-view">
<button class="btn btn-info" ng-click="createGameplanWithSelectedMembers(team)">Spielplan erstellen</button>
</div>
</div>
</div>
This is my Controller:
app.controller('modalCreateGameplanController', ['$scope', '$timeout', '$http', '$firebaseArray', '$firebaseObject', function ($scope, $timeout, $http, $firebaseObject, $firebaseArray) {
$scope.selectUsers = 'Teilnehmer';
$scope.$on('modal', function (event, args) {
var ref = firebase.database().ref("users");
var teams = $firebaseObject(ref);
teams.$loaded().then(function () {
$scope.teams = [];
angular.forEach(teams, function (key) {
$scope.teams.push({
allUserTeamName: key.firstname,
allUserTeam: key.team
});
$scope.selectMembers = function (key) {
console.log(key);
};
$scope.createGameplanWithSelectedMembers = function () {
console.log(teams);
};
});
});
});
}]);
In the view use ng-disabled and use selected length as condition to disable the button .
<div class="col-md-12">
<ul class="list-group">
<li ng-repeat="team in teams" class="list-group-item">{{ team.allUserTeamName + " - " + team.allUserTeam }}
<i class="fa fa-plus-circle" aria-hidden="true" ng-init="item.isClicked = false" ng-click="selectMembers(team); item.isClicked =!item.isClicked" ng-class="{clicked : item.isClicked}"></i>
</li>
</ul>
</div>
<div class="modal-footer">
<div class="col-md-12">
<div class="row pad-team-selection-view">
<button class="btn btn-info" ng-click="createGameplanWithSelectedMembers(team)" ng-disabled="selectCount==8">Spielplan erstellen</button>
</div>
</div>
</div>
In the controller keep a tracker for selected items $scope.selectCount
app.controller('modalCreateGameplanController', ['$scope', '$timeout', '$http', '$firebaseArray', '$firebaseObject', function ($scope, $timeout, $http, $firebaseObject, $firebaseArray) {
$scope.selectUsers = 'Teilnehmer';
$scope.$on('modal', function (event, args) {
var ref = firebase.database().ref("users");
var teams = $firebaseObject(ref);
teams.$loaded().then(function () {
$scope.selectCount=0;
$scope.teams = [];
angular.forEach(teams, function (key) {
$scope.teams.push({
allUserTeamName: key.firstname,
allUserTeam: key.team
});
$scope.selectMembers = function (key) {
$scope.selectCount=$scope.selectCount+1;
console.log(key);
};
$scope.createGameplanWithSelectedMembers = function () {
console.log(teams);
};
});
});
});
}]);

Angularjs order by not working properly

I'm facing a little problem with order by that i could not underdstand.
When i reoder the array i can see that every thing is working perfectly, but the problem is in the ng-click function of the list.
For example if i have this array:
$scope.ticketsEncour = [
{_id: 1, vendeur: 'John Doe', date_ticket: '18:52', total: 50},
{_id: 2, vendeur: 'Foo Bar', date_ticket: '12:12', total: 20},
{_id: 3, vendeur: 'John Smith', date_ticket: '11:02', total: 10},
{_id: 4, vendeur: 'Test Test', date_ticket: '05:10', total: 6000}
]
And this is ther reoder and click functions:
$scope.reverse = false;
$scope.orderItems = function (item) {
$scope.reverse = !$scope.reverse;
if (item != undefined) {
if (item == $scope.orderItem) {
$scope.orderType = $scope.orderType == '+' ? '-' : '+';
}
else {
$scope.orderItem = item;
$scope.orderType = '+';
}
}
$('.iconOrder').removeClass('up').removeClass('down');
if ($scope.orderType == '+') {
$('.iconOrder[name="' + $scope.orderItem + '"]').addClass('down')
}
else {
$('.iconOrder[name="' + $scope.orderItem + '"]').addClass('up')
}
return $scope.orderType + $scope.orderItem;
}
$scope.goToCaissePage = function (id) {
id = id.replace("app/caisse/", "");
console.log(id);
};
And my Html Code
<ion-list class="list articlesList swipedList" show-delete="showDelete">
<ion-item class="item item-button-right stable-bg">
<span class="row">
<span class="col col-20" ng-click="orderItems('vendeur')">
<strong>Vendeur</strong>
<div class="iconOrder" name="vendeur">
<i class="icon ion-android-arrow-dropup"></i>
<i class="icon ion-android-arrow-dropdown"></i>
</div>
</span>
<span class="col col-20" ng-click="orderItems('date_ticket')">
<strong>Heure</strong>
<div class="iconOrder" name="date_ticket">
<i class="icon ion-android-arrow-dropup"></i>
<i class="icon ion-android-arrow-dropdown"></i>
</div>
</span>
<span class="col col-10" ng-click="orderItems('total')">
<strong>Total</strong>
<div class="iconOrder" name="total">
<i class="icon ion-android-arrow-dropup"></i>
<i class="icon ion-android-arrow-dropdown"></i>
</div>
</span>
</span>
</ion-item>
<ion-item class="item item-button-right pad-item" ng-repeat="ticket in ticketsEncour | orderBy : orderBy : orderItem:reverse track by $index">
<span class="row">
<span class="col col-20 col-pad" ng-click="goToCaissePage('app/caisse/{{ticket._id}}')">
<div>
{{ ticket.vendeur }}
</div>
</span>
<span class="col col-20 col-pad" ng-click="goToCaissePage('app/caisse/{{ticket._id}}')">
<div>
{{ ticket.date_ticket | date:'HH:mm' }}
</div>
</span>
<span class="col col-10 col-pad" ng-click="goToCaissePage('app/caisse/{{ticket._id}}')">
<div>
{{ ticket.total.toFixed(2) }}€
</div>
</span>
</span>
</ion-item>
</ion-list>
When i click on any item of the ng-repeat it shows the right id in the console. But when i use the reorder i can is that the HTML has changed but the ng-click function render always the old one:
click on index 0 => console 1 (perfect)
After reoder with any type:
click on index 0 => console 1 (expected 3 for example)
Thanks
Update: changed the array name (copy cut error)
Updated with #Weijian suggestion
I suggest using the orderBy that uses the scope variables directly. This is also the method suggested by the angular docs.
js
$scope.reverse = false;
$scope.orderItems = function (item) {
if( item == $scope.orderItem ){
$scope.reverse = !$scope.reverse;
}
$scope.orderItem = item;
$('.iconOrder').removeClass('up').removeClass('down');
if( $scope.reverse ){
$('.iconOrder[name="' + $scope.orderItem + '"]').addClass('down');
}
else {
$('.iconOrder[name="' + $scope.orderItem + '"]').addClass('up');
}
}
html
orderBy:orderItem:reverse
https://docs.angularjs.org/api/ng/filter/orderBy
this way is cleaner since you avoid the mixed use of the orderItems function.
I fixed the issue, i was from the track by $index in the ng-repeat loop

How update list in AngularJS?

I created one TODO List in AngularJS but I didn't finish the update function. I have some difficulty.
How do I create the update function?
Link: https://plnkr.co/edit/XfWoGVrEBqSl6as0JatS?p=preview
<ul class="list-todo">
<li ng-repeat="t in tasks track by $index">
<div class="row">
<div class="six columns">
<p>{{ t }}</p>
</div>
<div class="three columns">
<button class="button" ng-click="update()">update</button>
</div>
<div class="three columns">
<button class="button" ng-click="delete()">x</button>
</div>
</div>
</li>
</ul>
Angular Code:
angular.module('todoTest', [])
.controller('todoController', function($scope) {
$scope.tasks = [];
$scope.add = function() {
$scope.tasks.push($scope.dotask);
}
$scope.update = function(){
$apply.tasks.push($scope.dotask);
}
$scope.delete = function() {
$scope.tasks.splice(this.$index, 1);
}
})
If you want to update the value you have to pass as parameter the position of the task inside the tasks array ($index is the position):
<button class="button" ng-click="update($index)">update</button>
And then the update function would be:
$scope.update = function(index){
$scope.tasks[index] = $scope.dotask;
}
Is that what you needed?
Button for updating. Visible only while updating.
<div class="row">
<button type="submit" class="u-full-width button button-primary">Criar Tarefa</button>
<button ng-show="updateMode" ng-click="update()" type="button" class="u-full-width button button-primary">Update</button>
</div>
New update function.
$scope.update = function(index) {
if ($scope.updateMode) {
$scope.tasks[$scope.updateIndex] = $scope.dotask;
$scope.updateMode = false;
} else {
$scope.dotask = $scope.tasks[index];
$scope.updateMode = true;
$scope.updateIndex = index;
}
If you click update on the task it will make the big update button visible and bring the old todo to the input. After hitting the big update button the todo task will update.
Plunker

Ionic Modal: clear all fields on click/cancel

Ive tried to use this with the current view scope and also by adding its own controller. No success in clearing all fields on cancel button click. All I need is to clear the fields.
Here is my in my controller modal :
var myApp = angular.module('starter.controllers');
function TalkSearchPageCtrl($scope, TalkSearch, $ionicModal) {
var nextPageNum = 1;
$scope.noMoreItemsAvailable = false;
var nextPageNum = 1;
$scope.loadMore = function() {
TalkSearch.getList(nextPageNum, {
}, $scope.idsToExclude, $scope.backResult).success(function(items) {
if (typeof(items.idsToExclude) !== undefined) {
$scope.idsToExclude = items.idsToExclude;
$scope.backResult = true;
} else {
$scope.idsToExclude = undefined;
$scope.backResult = undefined;
}
// error check when it's not loading
if (items.talks.length != 0) {
i = 0;
while (i != items.talks.length - 1) {
$scope.talks.push(items.talks[i]);
i++;
}
nextPageNum++;
} else {
$scope.noMoreItemsAvailable = true;
}
$scope.$broadcast('scroll.infiniteScrollComplete');
});
};
$scope.talks = [];
$scope.categories = [
];
$scope.checkedCategories = [];
$scope.toggleCheck = function(category) {
if ($scope.checkedCategories.indexOf(category) === -1) {
$scope.checkedCategories.push(category);
} else {
$scope.checkedCategories.splice($scope.checkedCategories.indexOf(category), 1);
}
};
$scope.getValues = function(filter) {
console.log(filter);
if (filter.length || filter !== undefined) {
$scope.userFilter = {};
$scope.userFilter.categories = [];
$scope.userFilter.filters = {};
$scope.userFilter.filters = angular.copy(filter);
var categories = $scope.checkedCategories;
$scope.userFilter.categories = categories;
getFiltersService.filter = angular.copy(filter);
console.log($scope.userFilter);
// console.log(getFiltersService.filter);
}
};
$scope.reset = function() {
console.log($scope.userFilter);
// $scope.modal.hide();
// $scope.userFilter.filters = null;
// $scope.userFilter.categories = null;
// $scope.userFilter = {};
console.log($scope.userFilter);
};
$ionicModal.fromTemplateUrl('my-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
}
myApp.controller('TalkSearchPageCtrl', ['$scope', 'TalkSearch', '$ionicModal', TalkSearchPageCtrl]);
$ionicModal.fromTemplateUrl('my-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
Here is my html script template :
<script id="my-modal.html" type="text/ng-template">
<ion-modal-view>
<ion-header-bar class="bar bar-header schoolinkscolor headerSection" ng-controller="TalkFilterPageCtrl">
<div class="row padding0">
<div class="col">
<div class="button button-white closeModal" side="right" ng-click="reset(talkfilter);hideButton=false;showDetails=false;"><span>Cancel</span></div>
</div>
<div class="col">
<div class="light headerTitle"><span class="light">Schoo</span><span class="color-black">Links</span></div>
</div>
<div class="col">
<div class="button button-white searchButton" side="left"><span>Search</span></div>
</div>
</div>
</ion-header-bar>
<ion-content class="has-header">
<div class="talkFilterContainer">
<section>
<div class="col padding0">
<div class="list list-inset">
<label class="item item-input">
<i class="icon ion-search placeholder-icon"></i>
<input type="text" placeholder="Search" ng-model="talkfilter.searchTalk" ng-change="getValues(talkfilter)" ng-model-options="{ debounce: 1000 }">
</label>
</div>
</div>
</section>
<div class="row padding clearboth"></div>
<section>
<div class="list padding">
<label class="item item-input item-select">
<div class="input-label">
Language:
</div>
<select ng-options="author for author in ['Mandarin','Spanish','Portuguese']" ng-model="talkfilter.selectLanguage" ng-init="author = 'Select Preferred Language'" ng-change="getValues(talkfilter)">
<option value="">Select Preferred Language</option>
</select>
</label>
</div>
</section>
<div class="row padding clearboth"></div>
<section>
<div class="list padding">
<label class="item item-input item-select">
<div class="input-label">
Author Type:
</div>
<select ng-options="author for author in ['Consultant','School','Student']" ng-model="talkfilter.authorType" ng-init="author = 'Select By Author Type'" ng-change="getValues(talkfilter)">
<option value="">Select By Author Type</option>
</select>
</label>
</div>
</section>
<div class="row padding clearboth"></div>
<section class="padding">
<ion-list>
<ion-item ng-repeat="category in categories track by $index" ng-class="{ 'hidden': ! showDetails && $index > 2}">
<ion-checkbox value="{{category}}" ng-model="$index" ng-click="toggleCheck(category); getValues(talkfilter)">{{category}}</ion-checkbox>
</ion-item>
</ion-list>
<div class="row">
<button class="button button-full button-clear" ng-click="showDetails = ! showDetails;hideButton=true" ng-show="!hideButton">See All Categories</button>
</div>
</section>
</div>
</ion-content>
</ion-modal-view>
Here is my reset function:
var Talk = this;
Talk.reset = function(filter) {
console.log(filter);
filter = null;
};
Also tried with $scope :
$scope.reset = function(filter) {
console.log(filter);
filter = null;
};
***Update:
$scope.reset = function(filter) {
$scope.userFilter = null; //does not work. none of these variations work.
$scope.userFilter = '';
};
Both of these methods return undefined. But if i put the button in the body it clears the fields. I need the button in the header.
Also tried inlining the reset with:
<button ng-click="talkfilter=null"></button>
The problem is that you are not passing anything in the filter function with the ng-click, because your $scope.userfilter is not defined throughout the controller.
Adding $scope.userFilter = {} like you have done inside of getValues, outside of that function should give you the desired result if you do your reset function like so....
function TalkSearchPageCtrl($scope, TalkSearch, $ionicModal) {
$scope.userFilter = {};
...
$scope.reset = function(filter) {
console.log(filter); \\Make sure this is the object
$scope.userFilter = null; \\Set it to null or {}
}`

Sorting object in angularjs whilst paginating

I have data coming from a server that I want to display. This data is being paginated and also sorted. The relevant part of the controller is as follows:
appControllers.controller('PostsCtrl',
['$scope', 'Restangular', 'messageCenterService',
'$location', '$anchorScroll',
'$filter',
function ($scope, Restangular, messageCenterService,
$location, $anchorScroll, $filter) {
// Get all posts from server.
var allPosts = Restangular.all('api/posts');
allPosts.getList().then(function (posts) {
$scope.posts = posts;
$scope.predicate = 'rank';
$scope.reverse = false;
$scope.itemsPerPage = 10;
$scope.currentPage = 1;
$scope.totalItems = $scope.posts.length;
$scope.pageCount = function () {
return Math.ceil($scope.totalItems / $scope.itemsPerPage);
};
$scope.$watch('currentPage + itemsPerPage',
function () {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage),
end = begin + $scope.itemsPerPage;
$scope.position = (10 * ($scope.currentPage - 1));
$scope.filteredPosts = $scope.posts.slice(begin, end);
$location.hash('top');
// call $anchorScroll()
$anchorScroll();
});
});
Here is the html:
<li class="list-group-item" ng-repeat="post in filteredPosts | orderBy:predicate:reverse">
<div class="row-fluid">
<div class="col-sm-1 ">
<p style="margin-top: 1em">{{($index + 1) + position}}.</p>
</div>
<div class="col-sm-1 v-center">
<i class="fa fa-angle-up"></i> <br />
<small>{{post.votes}}votes</small> <br />
<i class="fa fa-angle-down"></i>
</div>
<div class="col-sm-8">
<h4><a href={{post.url}}>{{post.title}}</a></h4>
<div>
<ul class="list-inline">
<li ng-repeat="tag in post.tags">
<span class="fa fa-tag"></span>
<button ng-click="getTags(tag.id)">{{tag.name}}</button>
</li>
</ul>
<div>
<em>{{ post.created_at | timeAgo}}</em>
by <cite>{{post.author.username}}</cite>
</div>
<div>
<a href ng-click="select(post)">
<span class="fa-stack fa-2x">
<i class="fa fa-comment fa-stack-2x"></i>
<strong class="fa-stack-1x fa-stack-text fa-inverse">
{{post.comments.length}}
</strong>
</span>
</a>
</div>
</div>
<div class="panel" ng-show="isSelected(post)">
<ul class="nav nav-list" ng-repeat="comment in post.comments">
<li class="list-group-item">
<strong><cite>{{comment.author.username}}</cite></strong>
{{comment.updated_at | timeAgo }}
<p>{{comment.message}}</p>
</li>
</ul>
<form name="CommentForm" novalidate role="form" ng-if="user.isLoggedIn" ng-submit="CommentForm.$valid && comment(post)">
<label for="InputComment">Add a Comment</label>
<textarea ng-model="newComment.message" class="form-control" id="InputComment" rows="3" required></textarea>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</li>
<pagination total-items="totalItems" items-per-page="itemsPerPage"
ng-model="currentPage" ng-change="pageChanged()"></pagination>
I need some help with figuring out how to filter the order in which the data is displayed on the page. I have read other questions which ask about sorting but I did not see any where the content is also paginated with angularjs. The question I have is how do I do a live filter considering that I have objects coming back from the server and the content is then paginated?
You could create a paging filter, and combine it with orderBy to simulate filteredPosts.
app.filter('page', function () {
return function (input, start, end) {
return input.slice(start, end);
};
});
Then you can apply both filters in your template.
ng-repeat="post in posts | orderBy:predicate:reverse | page:begin:end"
You can use the orderBy filter also programmatically to sort your array
$scope.posts = posts;
$scope.posts=$filter('orderBy')($scope.posts,'rank',false );
$scope.itemsPerPage = 10;
...
$filter u have already as a dependency in your controller

Categories