I just started learning angular
and I have a question related to ng-repeater
I have an ng-repeater like:
<div ng-if="!promo.promotion.useHTML"
class="{{promo.promotion.monetateId}}"
ng-repeat="promo in promotions track by promo.promotion.slotId">
<div ng-if="!promo.useHTML">
<img ng-src="{{promo.promotion.imageURL}}"
ng-click="promoOnClick(promo.promotion.promotionURL)"/>
</div>
I want to have a different ng-click function on second element of repeater.
How would I get this?
You can try using $index variable which contains the repeater array offset index. You can use it to build conditional statements in your repeater.
<div ng-if="!promo.promotion.useHTML" class="{{promo.promotion.monetateId}}" ng-repeat="promo in promotions track by promo.promotion.slotId">
<div ng-if="!promo.useHTML && $index !== 2">
<img ng-src="{{promo.promotion.imageURL}}" ng-click="promoOnClick(promo.promotion.promotionURL)"/>
</div>
<div ng-if="!promo.useHTML && $index == 2">
<img ng-src="{{promo.promotion.imageURL}}" ng-click="promoOnClickAnotherFunction(promo.promotion.promotionURL)"/>
</div>
</div>
Or as suggested by comment below
<div ng-if="!promo.promotion.useHTML" class="{{promo.promotion.monetateId}}" ng-repeat="promo in promotions track by promo.promotion.slotId">
<div ng-if="!promo.useHTML>
<img ng-src="{{promo.promotion.imageURL}}" ng-click="($index==1) ? function1() : function2()"/>
</div>
</div>
or as a third option, you can pass the index into the callback function as a second parameter and move your logic into your controller.
and in your callback, check the index and ... based on the index call your
function1, or function 2. Its a good idea to move logic away from your templates/views.
even better option would be creating/setting your promote() function function in your controller. E.g when you load your promotions array/objects, loop over them and set their promote function based on ... whatever your requirements are.
var i;
var yourPromoteFunctionForSecondElement = function( promo_object ) {
/*do your promo specific stuff here*/
}
for (i = 0; i < promotions.length; i++) {
var promotion = promotions[i];
if ( i == 1 ) {promotion.promote = yourPromoteFunctionForSecondElement(promotion);}
else if () {promotion.promote = someOtherPromoteFunction(promotion);}
else {/*etc*/}
}
Related
So, I have created an array of all instances of certain classes.
anchors = [];
$('.a-all').each(function() {
anchors.push($(this));
});
if ( viewport().width > 1366 ) {
sub_anchors = $('.a-lg');
} else if ( viewport().width > 1024 ) {
sub_anchors = $('.a-md');
} else if ( viewport().width > 768 ) {
sub_anchors = $('.a-sm');
} else {
sub_anchors = $('.a-xs');
}
sub_anchors.each(function() {
anchors.push($(this));
});
Then I set a variable 'current' and made it the object with the class '.active'.
current = $('.active');
Now, with jQuery, I want to be able to find the next and previous DOM object relative to .active that exists inside the array I have created.
The array is not in order, and will change at different widths.
Is this possible, or is there a better logic to use here?
EDIT: Adding markup for context.
<div class="website-wrapper w-d-100 h-d-100">
<div class="page-wrapper">
<section id="landing-slider" class="a-all active">
<div class="w-d-100 h-d-100">
This is the homepage landing slider... thing.
</div>
</section>
<section id="about" class="a-all">
<div class="w-d-100 h-d-50 w-sm-75 h-sm-100 dark">
About Panel 1 (75)
</div>
<div class="w-d-100 h-d-50 w-sm-25 h-sm-100">
About Panel 2 (25)
</div>
</section>
<section id="clients" class="a-all">
<div class="w-d-100 h-d-50 w-sm-50 h-sm-100">
Clients Panel 1 (50)
</div>
<div class="w-d-100 h-d-50 w-sm-50 h-sm-100 dark">
Clients Panel 2 (50)
</div>
</section>
<section id="services" class="a-md">
<section class="a-sm">
<div class="w-d-100 h-d-100 w-sm-50 h-sm-100 dark">
Services Panel 1 (50)
</div>
</section>
<section class="a-sm">
<div class="w-d-100 h-d-100 w-sm-50 h-sm-100">
Services Panel 2 (50)
</div>
</section>
</section>
<section id="lets-work" class="a-all">
<div class="w-d-100 h-d-100 dark">
Lets work together! (100)
</div>
</section>
</div>
</div>
Updated answer (now you've shown your HTML)
Since your .a-all elements are siblings (sometimes non-adjacent), you can use prevAll and nextAll, no need for the anchors array at all:
var next = $(".active")..nextAll(".a-all").first();
// or
var previous = $(".active").prevAll(".a-all").first();
If you want to find a .a-md or .a-sm, just use that as the prevAll/nextAll selector.
Original answer
Now, with jQuery, I want to be able to find the next and previous DOM object relative to .active that exists inside the array I have created.
It would be easier if you didn't make an array out of your initial jQuery object. Instead, just remember the object:
var anchors = $(".a-all");
Later, if you want to know where an element is in that array, you can use index(element):
var index = anchors.index($(".active")[0]);
Then you can get the previous like this:
var prev = index > 0 ? anchors.eq(index - 1) : $();
...or the next like this:
var next = index < anchors.length - 1 ? anchors.eq(index + 1) : $();
But if you want to use an array of jQuery instances (like the one you built) instead, you can use findIndex:
var anchors = $(".a-all").map(function() { return $(this); }).get();
// ...
var active = $(".active")[0]; // Note the [0] to get raw element
var index = anchors.findIndex(function(entry) {
return entry[0] === active;
});
// ...
var prev = index > 0 ? anchors[index - 1] : $();
// ...
var next = index < anchors.length - 1 ? anchors[index + 1] : $();
I've set a value when the user click vote choice. Its working.
.then(function(response) {
localStorage.setItem('isClicked', 'Yes');
var i = +localStorage.key("nid");
var nidId = 'nid' + localStorage.length;
localStorage.setItem(nidId, vm.nid);
vm.clickedBefore = true;
})
This is my HTML scope:
<div class="card myfunc" ng-repeat="myfunc in myfuncPage.myfuncs" id="{{myfunc.nid}}" >
<div class="item item-text-wrap">
<h2 class="item-icon-left"><i class="icon ion-ios-analytics"></i>
{{myfunc.title}}</h2>
</div>
<div class="item item-text-wrap" ng-show="localstorage">
<img ng-src="{{myfunc.field_image.und[0].imgPath}}"/>
<p class="custom-class" ng-bind-html='myfunc.body.und[0].value'>
</p>
<ul ng-repeat="vote in myfunc.advmyfunc_choice">
<li ng-repeat="voteselect in vote">
<div class="row">
<button class="col button button-outline button-dark" ng-click="myfuncPage.sendNid(myfunc);myfuncPage.sendVote(voteselect);showVoted = ! showVoted" >{{voteselect.choice}}</button>
<div class="voted-screen" ng-show="showVoted">
<h3>Thanks.</h3>
</div>
</div>
</li>
</ul>
</div>
</div>
In basically, I need remember the div via localStorage and when the page refresh, hide choice divs.
ng-show="showVoted" working on click but I need on refresh.
What is the best way to do it? Thanks.
I am not sure what local storage module you are using, so I can't be specific, but I would write factory that handles the retrieval and storage of the values you need
(function () {
var voteFactory = function (localStorage) {
return {
getVote: function (key) {
var isVoted = false;
// get local storage item, set voted etc
var voted = localStorage.getItem(key);
if(voted) {
isVoted = voted;
}
return isVoted;
},
setVote: function(key, value) {
localStorage.setItem(key,value);
}
};
};
app.factory('voteFactory', ['localStorage', voteFactory]);
})();
Then within the scope controller/directive you are using to show or hide you would have a function:
$scope.showVoted = function(key) {
return voteFactory.getVote(key);
}
then ng-show="showVoted(theidentifieryouwantouse)"
It is also worthwhile to mention I would use ng-if instead of ng-show. To be more efficient you could store your votes as an array instead of individual values and do a check to see if you have retrieved all values, get from local storage if not. Then your functions would interrogate retrieved array instead of repeated calls to local storage. I would also advice maybe using a promise in the factory because retrieval from local storage could be delayed causing some ui oddities.
Hopefully this is along the lines of what you are looking for. I can elaborate if needed.
I have a problem with referencing an element rendered in ng-repeat loop. My code is:
<div class="cars-container" data-ng-repeat="car in cars">
<div data-ng-show="$index == 2">
<div id="clock"></div>
</div>
<div class="rental-car-box row">
</div>
</div>
There are 4 cars displayed on page. After the second one i want to show a div#clock and then do some operations on it in a controller.
The code In controller:
$scope.cars = [];
cars is filled on page init with ajax call. When results come back I tried to watch the cars.length:
$scope.$watch('cars.length', function(newValue, oldValue) {
if( newValue > 2 ) {
console.log(angular.element('#clock').length);
}
});
but the console log shows 0.
Also tried: watching #clock:
$scope.len = angular.element('#clock').length;
$scope.$watch('len', function(n, o) {
console.log(n, o)
})
but no luck here either. It shows 0 all the time.
Any idea how this can be acomplished? Any help will be appreciated.
Thanks in advance
Rafal
i'm using fabric js and trying to remove group of items when try to remove the parent item of group. following is my code.
jQuery(document).on('click', ".deleteBtn", function () {
if (canvas.getActiveObject()) {
var product_id = canvas.getActiveObject().get('product_id');
}
var canvasObj = canvas.getObjects();
for(var i = 0; i < canvasObj.length; i++){
var objRef = canvasObj[i];
var accessoryId = objRef.get('accessory_product_id');
var product_type = objRef.get('product_type');
if(accessoryId == product_id && product_type == "accessory"){
canvas.remove(objRef);
}
}
});
code is actually working, but not removing all items with same accessoryId and product_type parent item which is the active object trying to remove and two other items are removing properly. only two items left on canvas. there are all 5 items in group. those are images. i'm unable to find the issue please help. thanks!
HTML code
<div id="content-tab-3" class="visualiser-product-category content-tab active">
<ul>
<li>
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter_Spice.png" class="visualizer-product-img" alt="Placeholder" data-quantity="1" data-product_type="parent" data-product_id="343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Desk-Floral.jpg" class="hide accessory-343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Garland.jpg" class="hide accessory-343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Tabletop.jpg" class="hide accessory-343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Wreath.jpg" class="hide accessory-343">
</li>
</ul>
</div>
Hello i noticed on your code that you try to get the active's object id, but no matter if there is active object or not you proceed to the loop, to delete the objects!!
Maybe, that causes the problem.
I'm going to show an example with forEach() function, but proceed to delete objects ONLY if there is active object:
jQuery(document).on('click', ".deleteBtn", function () {
//only if there is active object, do i delete objects
if (canvas.getActiveObject()) {
//get productId of active object
var product_id = canvas.getActiveObject().product_id;
//loop on the canvas objects
canvas.getObjects().forEach(function (object) {
if(object.accessoryId == product_id && object.product_type == "accessory"){
canvas.remove(object);
}
});//end forEach
}//end if
});//end 'click'
Hope helps, good luck.
I'm using ng-repeat with a limitTo filter and a button to raise the limit when clicked. Is there any way to check if the next item in the ng-repeat iteration exists/count how many more items there are so that i can hide the 'load more' button/show how many more items there are.
below is sort of an example of what I am trying to do:
<div ng-repeat="comment in collection.data | limitTo:commentLimit">
{{comment.text}}
<div ng-show="filteredItems[$index + 1]" ng-click="increaseLimit()">load more (3 more replies)</div>
</div>
You can do something similar to this codepen:
http://codepen.io/anon/pen/waxOZL
<div ng-repeat="comment in collection.data | limitTo:commentLimit">
{{comment.text}}
</div>
<div ng-show="collection.data.length > commentLimit" ng-click="increaseLimit()">load more (3 more replies)</div>
Also, you should put the load more link outside the ng-repeat to show it only once.
Ideally, I think what you want to do is set an increment value in your scope, and add a new function called nextIncrementAmount which will help you display the number of new replies the button will add when clicked.
$scope.commentLimit = 3;
$scope.incrementStep = 3;
//use this function to increase the filter limit
$scope.increaseLimit = function() {
var newLimit = $scope.commentLimit + $scope.incrementStep;
$scope.commentLimit = (newLimit < $scope.collection.data.length) ? newLimit : $scope.collection.data.length;
}
//use this function to show the number of replies the increment button will increment by.
$scope.nextIncrementAmount = function() {
var newLimit = $scope.commentLimit + $scope.incrementStep;
return (newLimit < $scope.collection.data.length) ? $scope.incrementStep : $scope.collection.data.length - $scope.commentLimit;
}
Then in your view you'll want to do something like this:
<div ng-repeat="comment in collection.data | limitTo:commentLimit">
{{comment.text}}
</div>
<div ng-if="collection.data.length != commentLimit"
ng-click="increaseLimit()">
load more (<ng-pluralize count="nextIncrementAmount()"
when="{
'1': '{} more reply',
'other': '{} more replies',
}"> </ng-pluralize>)
</div>