check if button is active or not in controller - angularjs

i have a single toggle button that changes color when clicked active. but now i'm stuck as to how i'll get the value of the button (active or inactive) in my controller. how should i approach this?
here's the error code:
TypeError: Cannot read property 'clicked' of undefined
here's the html code:
<button class="button button-clear icon ion-star button-energized" ng-model="singleTog" ng-click="toggleButton(item.name)" ng-class="singleTog.clicked?'button-energized':'button-dark'" ></button>
and here's the controller.js code:
$scope.toggleButton = function(candidateName)
{
$scope.singleTog.clicked=!$scope.singleTog.clicked
if($scope.singleTog.clicked==true)
{
if(favoriteList.indexOf(candidateName) == -1) //does not exist in array
{
$scope.numbers.push(candidateName);
}
}
else
{
if(favoriteList.indexOf(candidateName) != -1) //exists in array
{
var index = $scope.favoriteList.indexOf(candidateName);
$scope.favoriteList.splice(index, 1);
}
}
alert('favorites = ' + favoriteList);
}

Define an emty object as $scope.singleTog = {}
Try this
$scope.singleTog = {}
$scope.toggleButton = function(candidateName)
{
$scope.singleTog.clicked=!$scope.singleTog.clicked
if($scope.singleTog.clicked==true)
{
if(favoriteList.indexOf(candidateName) == -1) //does not exist in array
{
$scope.numbers.push(candidateName);
}
}
else
{
if(favoriteList.indexOf(candidateName) != -1) //exists in array
{
var index = $scope.favoriteList.indexOf(candidateName);
$scope.favoriteList.splice(index, 1);
}
}
alert('favorites = ' + favoriteList);
}

If you just want to change the color of the button when it is active or inactive you can use ng-class for that:
ng-class="$variableToEvaluate ? 'class-if-true' : 'class-if-false'"

Related

Disable submit button when duplicates in ng-repeat

In extending to the question how to disable submit button or make form invalid if i have any duplicates
Got Solution : here is my code
HTML
Submit
JS
$scope.myform.$setValidity('invalid',!((sorted[i-1] && sorted[i-1].voucherCode == sorted[i].voucherCode) || (sorted[i+1] && sorted[i+1].voucherCode == sorted[i].voucherCode)));
Somewhere in your Controller
$scope.hasDuplicate = function() {
var sorted;
sorted = $scope.csTagGrp[0].csTags.concat().sort(function(a, b) {
if (a.keys > b.keys) return 1;
if (a.keys < b.keys) return -1;
return 0;
});
return sorted.some(function(nth, i){
if(i> 0 && i < sorted.length) {
return ((nth[i - 1].keys == nth.keys) || (sorted[i + 1].keys == nth.keys));
}
return false;
});
};
In template
<button type="submit" ng-disabled="hasDuplicate()"> Save </button>

Custom angular directive controller not updating

I created my own angular directive which can simply be used as:
<basket-summary></basket-summary>
This element is used on my master template page (the index.html).
The directive is as follows:
/* Directive */
angular.module('ecommerceDirectives').directive('basketSummary', [function() {
return {
restrict : 'E',
scope: {},
replace: true,
controller : 'BasketController',
controllerAs: 'basketController',
bindToController: {
basketController : '='
},
templateUrl: function(element, attrs) {
if (typeof attrs.templateUrl == 'undefined') {
return 'app/views/basket-summary.html';
} else {
return attrs.templateUrl;
}
},
link: function (scope, element, attrs) {
console.log("test");
}
};
}]);
The templateUrl of this directive is as follows:
<div class="btn-group pull-right">
<a class="btn btn-warning" ng-click="basketController.viewBasket()"><span class="badge">{{basketController.getTotalQuantities()}}</span> <span class="hidden-xs">Shopping</span> Cart</a>
<button type="button" class="btn btn-warning dropdown-toggle" data-toggle="dropdown">
<span class="fa fa-caret-down"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu">
<div class="col-xs-12 cartItemHeader">
<h4>My Shopping Cart</h4>
</div>
<div class="quickCart" ng-repeat="cartItem in basketController.customerBasket.items">
<div class="col-xs-12 cartItemWrap">
<div class="col-xs-12 desc">{{cartItem.product.title}}</div>
<div class="col-xs-5 col-sm-8 price">{{cartItem.product.rrp_currency}} {{cartItem.product.rrp_amount}}</div>
<div class="col-xs-6 col-sm-3 units">Items: {{cartItem.quantity}}</div>
<div class="col-xs-1 trash"><a ng-click="basketController.deleteCartItem(cartItem.product.id)"><i class="fa fa-trash"></i></a></div>
</div>
</div>
</div>
And the BasketController is as follows:
/* Controller */
angular.module('ecommerceControllers').controller('BasketController', ['$rootScope', '$scope', '$route', '$location', 'CustomerBasketService', 'AppSettingService', 'StorageService', 'DEFAULT_CURRENCY_CODE', 'MERCHANT_ID_KEY', function($rootScope, $scope, $route, $location, CustomerBasketService, AppSettingService, StorageService, DEFAULT_CURRENCY_CODE, MERCHANT_ID_KEY) {
function basketProduct(product) {
this.id = product.id;
this.title = product.title;
this.categories = product.categories;
this.images = product.imaes;
this.created_on = product.created_on;
this.sku_code = product.sku_code;
this.lang = product.lang;
this.short_description = product.short_description;
this.attributes = product.attributes;
this.rrp_currency = product.rrp_currency;
this.rrp_amount = product.rrp_amount;
this.barcode_number = product.barcode_number;
this.last_modified_on = product.last_modified_on;
}
function basketItem(quantity, product) {
this.quantity = quantity;
this.product = new basketProduct(product);
}
function load() {
var basket = StorageService.get("customer_basket");
if (basket) {
for (var i = 0; i < basket.items.length; i++) {
var cartItem = basket.items[i];
cartItem = new basketItem(cartItem.quantity, cartItem.product);
basket.items[i] = cartItem;
}
}
return basket;
}
var basketController = this;
$scope.basketController = basketController;
basketController.customerBasket = load();
if (!basketController.customerBasket) {
basketController.customerBasket = {
shipping : null,
taxRate : null,
tax : null,
items : []
};
}
basketController.addCartItem = function(quantity, product) {
if (product == undefined || product == null) {
throw "No Product was specified.";
}
if (quantity == undefined || quantity == null) {
quantity = null;
}
var found = false;
if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
for (var i = 0; i < basketController.customerBasket.items.length; i++) {
var cartItem = basketController.customerBasket.items[i];
if (product.id === cartItem.product.id) {
found = true;
cartItem.quantity = cartItem.quantity + quantity;
if (cartItem.quantity < 1) {
basketController.customerBasket.items.splice(i, 1);
} else {
$rootScope.$broadcast('customerBasketItemUpdated', {item: cartItem});
}
}
}
}
if (!found) {
var cartItem = new basketItem(quantity, product);
basketController.customerBasket.items.push(cartItem);
$rootScope.$broadcast('customerBasketItemAdded', {item: cartItem});
}
basketController.saveBasket();
}
basketController.updateBasket = function() {
if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
for (var i = 0; i < basketController.customerBasket.items.length; i++) {
var cartItem = basketController.customerBasket.items[i];
if (cartItem.quantity < 1) {
basketController.customerBasket.items.splice(i, 1);
}
}
}
basketController.saveBasket();
}
basketController.deleteCartItem = function(productId) {
if (productId == undefined) {
throw "Product ID is required.";
}
if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
for (var i = 0; i < basketController.customerBasket.items.length; i++) {
var cartItem = basketController.customerBasket.items[i];
if (productId == cartItem.product.id) {
basketController.customerBasket.items.splice(i, 1);
}
}
}
//Save
basketController.saveBasket();
}
basketController.getCurrencyCode = function() {
var code = DEFAULT_CURRENCY_CODE;
if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
code = basketController.customerBasket.items[0].product.rrp_currency;
}
return code;
};
basketController.getTotalQuantities = function(id) {
var total = 0;
if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
for (var i = 0; i < basketController.customerBasket.items.length; i++) {
var cartItem = basketController.customerBasket.items[i];
if (id == undefined || id == cartItem.product.id) {
total += cartItem.quantity;
}
}
}
return total;
};
basketController.getTotalAmount = function(cartItem) {
var total = 0;
if (cartItem) {
total = (cartItem.quantity * cartItem.product.rrp_amount);
}
return total.toFixed(2);
};
basketController.getFinalTotalAmount = function() {
var total = 0;
if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
for (var i = 0; i < basketController.customerBasket.items.length; i++) {
var cartItem = basketController.customerBasket.items[i];
total += (cartItem.quantity * cartItem.product.rrp_amount);
}
}
return total.toFixed(2);
};
basketController.clearBasket = function() {
StorageService.set("customer_basket", null);
basketController.customerBasket = {
shipping : null,
taxRate : null,
tax : null,
items : []
};
$rootScope.$broadcast('customerBasketCleared', {});
}
basketController.saveBasket = function() {
if (basketController.customerBasket) {
StorageService.set("customer_basket", basketController.customerBasket);
$rootScope.$broadcast('customerBasketSaved', {});
}
}
basketController.checkout = function(serviceName, clearCart) {
if (serviceName == undefined || serviceName == null) {
serviceName = "PayPal";
}
switch (serviceName) {
case "PayPal":
basketController.checkoutPayPal(clearCart);
break;
default:
throw "Unknown checkout service '" + serviceName + "'.";
}
};
basketController.checkoutPayPal = function(clearCart) {
if (basketController.customerBasket && basketController.customerBasket.items && basketController.customerBasket.items.length > 0) {
// global data
var data = {
cmd: "_cart",
business: '', //parms.merchantID,
upload: "1",
rm: "2",
charset: "utf-8"
};
AppSettingService.getAppSetting(MERCHANT_ID_KEY).get().$promise
.then(function(result) {
data.business = result.value;
for (var i = 0; i < basketController.customerBasket.items.length; i++) {
var cartItem = basketController.customerBasket.items[i];
var ctr = i + 1;
data["item_number_" + ctr] = cartItem.product.sku_code;
data["item_name_" + ctr] = cartItem.product.title;
data["quantity_" + ctr] = cartItem.quantity;
data["amount_" + ctr] = cartItem.product.rrp_amount.toFixed(2);
}
// build form
var form = $('<form/></form>');
form.attr("action", "https://www.paypal.com/cgi-bin/webscr");
form.attr("method", "POST");
form.attr("style", "display:none;");
addFormFields(form, data);
$("body").append(form);
// submit form
form.submit();
form.remove();
if (clearCart) {
try {
basketController.clearBasket();
} catch (exception) {
}
}
}).catch(function(reason) {
console.log(reason);
});
}
};
basketController.viewBasket = function() {
$location.path("/basket");
$route.reload();
};
function addFormFields(form, data) {
if (data != null) {
$.each(data, function (name, value) {
if (value != null) {
var input = $("<input></input>").attr("type", "hidden").attr("name", name).val(value);
form.append(input);
}
});
}
}
return basketController;
}]);
My dilemma is as follows:
On my product page, I have product.html page (which is an angular view) and the "add to cart" button adds item to the cart but it doesn't update my cart summary button.
How do I make it that when I click the "add to cart" button that it update my cart and the number of items added to the cart?
The example image:
As you can see the orange button at the top right says that I have no items but there is 3 items in my cart already.
I tried various scoping allowed in directives but I seem to be failing to make it work.
PS: I am a newbie in AngularJS so please make your answer as simple to understand. :-)
The view product.html is linked to BasketController and this is the button that add item to cart.
<a class="btn btn-success btn-lg pull-right" role="button" ng-click="basketController.addCartItem(1, productController.selectedProduct)"><i class="fa fa-plus"></i> Add To Cart</a></div>
You have an isolated scope issue. The controller of your directive is not the same as the controller you want to use in your product page. See: scopes
I would suggest you to create a factory, which is always a singleton where you store your basket products and inject them in both, the directive and the products page

ng-class calling function on page load - AngularJS

This may be very simple but I can't seem to be able to successfully get the logic I want.
<div class="group-title" ng-class="{'group-hasError': !isValid(orderItem)}">
As you can see I'm adding a class group-hasError if the function isValid(orderItem) returns false.
Now the issue is that this is called on page load. But I don't want to call this function on page load rather when a submit button is called
<button id="add_modified_item" ng-click="isValid(orderItem)" class="btn btn-primary btn-fixed-medium pull-right">
How can I achieve this?
This is the function;
$scope.isValid = function(orderItem) {
var count = 0;
//By default make it true
var IsAllSelected = true;
angular.forEach(orderItem.menu_modifier_groups, function(group) {
var count = 0;
angular.forEach(group.menu_modifier_items, function(item) {
count += item.selected ? 1 : 0;
});
if (count == group.max_selection_points) {
IsAllSelected = true;
} else {
//if one item failed All select do return false
IsAllSelected = false;
}
});
return IsAllSelected;
}
Any advice appreciated
Defalut set
$scope.setValidClass=false;
View
<div class="group-title" ng-class="(setValidClass)? 'group-hasError':'')}">
set model with
//if IsAllSelected=false then set IsAllSelected to true
$scope.setValidClass=!IsAllSelected;
return IsAllSelected;

AngularJS - ngRepeat & ngShow & Custom Filter - Optimization

I wrote a simple filter that gets a localized text. I use it in a list. When a word is not found I want to hide the item. I manage to solve the problem like this:
<ion-item ng-repeat="(key, data) in details" ng-if="key != 'Id' && key != 'Invoices' && key != 'Number' && key != 'Attributes' && data && key!= null" ng-show="(key | translate: clientCode:'Payments':'es').length > 0">
<p style="float:left; text-transform: capitalize;">{{key | translate: clientCode:'Payments':'es'}}:</p>
<p style="float:right;">{{data}}</p>
</ion-item>
However I am using the filter twice in each item which makes me feel weird. Is there a better way to do this? Thanks you all very much.
If it helps here is my filter code:
.filter("translate", function(Text) {
var data = null, serviceInvoked = false;
function realFilter(input) {
for(var i = 0; i < data.length; i++)
{
if(data[i].Field == input)
{
//console.log(data[i].Description);
return data[i].Description;
}
}
}
testFilter.$stateful = true;
function testFilter(input, clientCode, type, lang) {
if( data === null ) {
if( !serviceInvoked ) {
serviceInvoked = true;
var texts = Text.query({"clientCode": clientCode, "type": type, "lang": lang});
texts.$promise.then(function() {
data = texts;
});
}
return "-";
}
else return realFilter(input);
}
return testFilter;
});

Cell template with filter in ng-grid

I created a cell template that depends on a filter, but the filter is not processed.
The cell is defined as {field:'status', displayName:'Status', cellTemplate: 'cell/statusCellTemplate.html'}] where the template is
<button class="btn btn-primary" ng-click="changeStatus(row.getProperty('id'),'{{row.getProperty(col.field) || switchStatus}}')">{{row.getProperty(col.field)}}</button>
EDIT
myapp.filter('switchStatus', function() {
return function(input) {
return (input == 'STOPPED') ? 'STARTED' : 'STOPPED';
};
});
The rendered cell is <button class="btn btn-primary ng-scope ng-binding" ng-click="changeStatus(row.getProperty('id'),'STOPPED')">STOPPED</button>. I expect STARTED for the second parameter.
Plunker: when clicking on STOPPED, the current status should be STARTED
Where does data come from? I think you meant to check if input is 'STOPPED' or 'STARTED' like this:
app.filter('switchStatus', function() {
return function(input) {
var out = "";
if (input == 'STOPPED') {
out = 'STARTED';
} else if (input == 'STARTED') {
out = 'STOPPED';
}
console.log(input + " " + out);
return out;
};
You could make your filter shorter by writing:
app.filter('switchStatus', function() {
return function(input) {
return (input == 'STOPPED') ? 'STARTED' : 'STOPPED';
};

Resources