Angular slow hide/show - angularjs

I have some code to hide and show slides as follows:
<img ng-src="{{slide}}" ng-repeat="slide in slides" ng-show="$index == onSlide">
<a id="previousButton" type="button" ng-show="onSlide" class="left carousel-control" ng-click="onSlide = onSlide - 1">
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
<a id="nextButton" type="button" ng-hide="onSlide == slides.length - 1" class="right carousel-control" ng-click="onSlide = onSlide + 1">
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
Performance is great when using the buttons, the slides switch immediately. However, if I change scope.onSlide in the controller, there is an extreme delay in the slide switching, although a console.log reveals scope.onSlide is indeed incrementing immediately. What could be causing the lag?
Relevant controller code:
scope.$on("videoTimeChanged", function(event, time) {
if (scope.videoState == "playing") {
if (time > scope.scenario.presentation[0].syncManifest[scope.onSlide]) scope.onSlide++;
}
});
As you can see, I'm listening for a time event, which will fire every 250 ms or so, and comparing the time to the time at which the slide is supposed to change. If the current time is greater, I increment the slide. when i watch the various parts of this in console.log, it all works perfectly behind the scenes.

That probably happens because ng-repeat creates a new scope, and in ng-show you assign a primitive value instead of an object.
Try creating an object in your controller like $scope.carousel.onSlide and assign ng-show to carousel.onSlide instead.
Please do refer to carousel.onSlide inside all ng-clicks as well.
a classic: https://egghead.io/lessons/angularjs-the-dot

Related

Variable showing as undefined

I am having trouble with passing the results of checkboxes from my view to the controller and just get "undefined" in the console log.
FYI - I have my controller as "camp".
In my view I have the following:
<div style="padding:20px;">
<h5>Add a Business</h5>
<md-content style="padding:20px;">
<md-checkbox
ng-repeat="business in camp.businesses"
ng-model="business.selected"
aria-label="Checkbox"
>
{{business.business_name}}
</md-checkbox>
</md-content>
<md-button class="md-raised" ng-click="camp.addBusinesses(business)">
<i class="fa fa-plus"></i> Add
</md-button>
</div>
In my controller I have the following function in an "angular.extend()"
addBusinesses: function(val){
console.log('Display Results: ', val);
}
If I just use the function to log the click event, it's fine. But when I try to pass the "business" object, it says "undefined".
What am I missing here???
The issue is your <md-button> is outside the ng-repeat. Your ng-repeat ends with the </md-checkbox> so when it gets to the button, business is indeed undefined.
Try reformatting your code so that the button is still within the scope of the ng-repeat. Maybe you want the repeat on the md-content instead? I'm not sure what the page is supposed to look like so I can't advise more than that.

NgClick on <li> NgClick inside of it

I have following code:
<ul class="dropdown-menu">
<li ng-click="setValue('X')" ng-class="selected === 'X' ? 'active' : 'not-active'"><span>X <i class="fa fa-times" ng-click="unselect()"/></span></li>
<li ng-click="setValue('Y')" ng-class="selected === 'Y' ? 'active' : 'not-active'"><span>Y <i class="fa fa-times" ng-click="unselect()"/></span></li>
</ul>
I am switching classes if the value is selected. I would like to add an event on icon (which is only visible when its is selected), however, whenever I click on the icon, two ng-click's are triggered. My question is: how can I disable the ng-click on the parent element, when the row is selected?
You need to add $event.stopPropagation() to your inner ng-click:
<i class="fa fa-times" ng-click="unselect(); $event.stopPropagation();"/>
This will prevent the ng-click on the parent element from being called.
When you write and event in a DOM element, it's invocation bubbles up to call event attached to all it's parent till HTML tags.
You can prevent this occurrence by preventing the event to propagate further. stopPropagation does exactly that. You can find, details here https://developer.mozilla.org/en/docs/Web/API/Event/stopPropagation
In your, unselect function, you can call like this
function unselect(event) {
event.stopPropagation();
// Your original code
}

angularjs how to trigger changes on object in scope

I have the $scope object (array of objects) like this
$scope.parts = [];
(content of $scope.parts is changing during 'run-time', not just filled once per page load)
Later, it some custom directive i show those parts in such manner:
<li ng-repeat="part in parts">
<span>{{part.name}}
<i class="fa fa-check"
tooltip="some tooltip"
...
</i>
</span>
</li>
According to some logic, i want to change 'fa-' class and tooltip text.
I can do it like this
<i class="fa"
ng-class="haveDescr(part.name)"
//and in directive's controller
$scope.haveDescr = function (partName) {
return someCondition ? 'fa-check' : 'fa-question-circle';
};
and so on for the tooltip, and... for every attribute i want to change?
Is there a better way, than to write a scope "check-function" for every attribute? How can i trigger changes in every single part/property of $scope.parts and do the DOM changes described above? What is the right "angular way" for this? Or, maybe it is possible to 'intercept' ng-repeat action and do everything there?
You can use ng-class with an 'object' expression.
<i class="fa" ng-class="{'fa-check' : part.name, 'fa-question-circle' : !part.name}">
You can use ng-class and title
<i ng-class="{'fa-check':showFaCheck(part.name), 'fa-question': !showFaCheck(part.name) }" title="{{getTooltip(part.name)}}"/>
Fiddle http://jsfiddle.net/4PYZa/303/

angularjs animate : how to have an instantaneous ng-show (without fade in) while the hide does a fade out

In need a directive that does an instantaneous show (without
fade in), and when it gets hidden (ng-show='false'), does a progressive
fade out.
here is my attempt :
http://plnkr.co/edit/bEzAlwjNOsxLodnawu3s?p=preview
<span ng-show="inProgress" class="animate-fade">
<i class="glyphicon glyphicon-ok"></i>
<span ng-if="inProgress">save in progress...</span>
<span ng-if="! inProgress">saved</span>
</span>
You can create a new animation class and define .new-anim to appear, and .new-anim-remove.new-anim-remove-active class selector to animate, although this would require you to use the $animate service.

Animate rows through a directive inside a ng-repeat

I'm building this application in Angular where a div table is formed by using ng-repeat through the following html:
HTML
<div ng-repeat="(key, value) in data.data.ipv4">
<div class="cellbody">{{value.descr}}</div>
<div class="cellbody">{{value.protocol}}</div>
<div class="cellbody">{{value.internip}}</div>
<div class="cellbody">{{value.internrange}}</div>
<div class="cellbody">{{value.externrange}}</div>
<div class="deletecell">
<span class="toggledelete" ng-click="deleteport($event, key, 4)">
<i class="icon-minus negativehover"></i>
</span>
<span class="toggledelete" style="display:none">
<span>PORT DELETED</span>
<span class="deletedportundo" ng-click="restoreport($event, $index, 4)">
UNDO
</span>
</span>
</div>
</div>
The last div of each row, has a visible clickable button which sends a delete order to the server via the deleteport() function, and then, if everything goes all right, starts an animation where the whole cell is hidden and the previously hidden span with class 'deletedportundo' shows up.
Anyway the thing is my controller looks like this:
Angular Javascript Controller
$scope.deleteport = function(e,f) {
postData.index = f;
$http.post('serverside/router.php', postData)
.success(function(data, status, headers, config){
if (data.status == 'ok') {
var elem = angular.element(e.target);
$(elem).parent().parent().parent().children('.cellbody').hide('fast');
$(elem).parent().parent().children('.toggledelete').toggle();
$(elem).parent().parent().parent().children('.deletecell').animate({
width: "100%"
}, 300 );
$(elem).parent().parent().parent().children('.deletecell').addClass('macdeleted');
}
});
}
Which visually works as expected, except that I am aware that I should not be manipulating the DOM in the controller; I have been unsuccessfully trying to integrate this into a directive, but because every row is independent of the others I have not been able to achieve the desired effect.
Daniel,
There is nothing wrong with manipulating DOM in the controller. However, I can suggest an easier way to do it than to navigate with those nasty parent().parent().parent().parent().parent() ... calls :) .
Just add an ng-show to the toggledelete div, than just do $scope.portDeleted = false in your controller. This also works for the .cellbody tags.
As for the .deletecell class you can use ng-class, and just do $scope.deletecell = some_value.
<div ng-class="{deletecell:deletecell}">
<span class="toggledelete" ng-click="deleteport($event, key, 4)">
<i class="icon-minus negativehover"></i>
</span>
<span class="toggledelete" style="display:none">
<span>PORT DELETED</span>
<span class="deletedportundo" ng-click="restoreport($event, $index, 4)">
UNDO
</span>
</span>
</div>
For animate, you can use ngAnimate (http://www.nganimate.org/)

Resources