We have a popup modal in our Angular application which contains, among other things, a <span> element which should appear, and then fade, when a certain button is clicked. This all works as expected. But there is one problem. When the modal first loads, the <span> momentarily appears, then fades out. The behavior is consistent with the <span> having ng-show set to true, but then set to false at the time the modal is loaded, triggering the fade out transition.
Here is the <span>:
<span id="fileLinkCopied" data-ng-show="copyLinkClicked"
class="text-fade float-right">file copied to clipboard</span>
But the varible $scope.copyLinkClicked is set to false when the controller loads, and hence we would expect to never even seen the <span> being rendered at load time.
Here is the relevant CSS:
.text-fade {
transition: all linear 500ms;
opacity: 1;
}
.text-fade.ng-hide {
opacity: 0;
}
This problem was discussed in this SO question, but no definitive solution was given. We have pondered turning off the animation for this element, but this may have problems as well.
Any solution which gets the job done within normative usage of Angular would be greatly appreciated.
One quick workaround would be to add another span tag as the parent of your span element. You can then add an ng-if condition to the parent element and use a variable that is set to false initially in the if condition. This would make sure that the child span is not rendered when the page loads and therefore you wouldn't see the animation. You can then set the value of that variable to true on document ready event.
Here is the <span>:
<span ng-if="firstLoad "><span id="fileLinkCopied" data-ng-show="copyLinkClicked"
class="text-fade float-right">file copied to clipboard</span><span>
In your controller add the following:
$scope.firstLoad = false;
angular.element(document).ready(function () {
$scope.firstLoad = true;
});
Related
I have a bool called isStarted that is initially set to false.
I have two divs, one that has:
hidden={isVisible}
and the other has:
hidden={!isVisible}
I have a href link that has a onclick that calls a function which changes the bool value to it's inverse value. I confirm this by also console.logging the bools value. Each time I click it the value changes.
However the the divs do not change visibility, it just keeps showing the first one.
div1:
<div
className="relative"
hidden={isVisible}
> div1 </>
div2:
<div
className="relative"
hidden={!isVisible}
> div 2 </>
I also confirmed these divs show independently by manually setting the isVisible to true and false at the start.
EDIT:
This way works to change the visibility also, but only works the first time when the app goes live:
{isVisible && <div>wow</div>}
However when I click and change the isVisible value it still won't change the divs.
The hidden HTML attribute does not exist. You might be looking for the display CSS attribute.
<div style={{ display: none }} />
Offtopic personal suggestion: I'd suggest you starting learning React using TypeScript from the beginning. TS will warn you when an attribute does not exist and help you on your learning path.
EDIT:
It is display: none (removes the element) or visibility: hidden (hides but still takes space. I might have been on drugs when writing this.
I have created a uib-accordion in my Angular website and can get most of the functionality I want, with dynamic content changing accordingly.
I am having trouble styling the uib-accordion-group dynamically.
<uib-accordion-group panel-class="panel-danger">
<uib-accordion-heading>
Accordion Heading 1
Is fine and colours the whole heading Red/Pink, I want to change this to panel-warning or panel-info based on other variables on the page.
<uib-accordion-group panel-class="{{getPanelColor()}}">
<uib-accordion-heading>
Accordion Heading 1
The function seems to be called correctly and is triggered correctly with ng-click elsewhere.
I appears that I cannot change the value panel-class uses dynamically. So in this instance getPanelColor() returns 'panel-danger', 'panel-info' or 'panel-warning' depending on other variables. If I print this return value out on the page in another div or whatever it changes correctly. If I refresh the page the correct colours are displayed for the changed panel-group.
Is there another way of setting the color - I don't know what the classes are for the accordion-group. I have tried changing the color of a div withing the panel, but this is a child element and does not change the color of the whole heading.
Any help much appreciated. (I'll come up with a JSFiddle if the question is not clear)
If you look at the HTML after the panel-class has changed and Angular has digested the change, you will see this line:
<div class="panel panel-danger" ... panel-class="panel-default">
That is, there is a mismatch between class and panel-class (the former has panel-danger, whereas the latter has panel-default). The uib-accordion-group directive simply does not handle the change in the wanted manner.
One workaround is to add ng-if to the whole group:
<uib-accordion-group ng-if="render" panel-class="{{getPanelColor()}}">
... and just before you want to change panel-class, remove the whole element temporarily, so that Angular re-renders it from scratch. Hopefully, the following code explains the principle:
$scope.render = true;
$scope.panelColor = 'panel-danger';
$scope.setPanelColor = function(val) {
$scope.panelColor = val;
$scope.render = false;
$timeout(function () {
$scope.render = true;
});
};
$scope.getPanelColor = function() {
return $scope.panelColor;
};
See the proposal in action: http://plnkr.co/edit/XfJiPnNi1z4F9cgIVxxw?p=preview. Press 'Clear panel color OK'.
The downside is that the removal of the element causes some flickering.
I have added another button 'Clear panel color FAIL' that shows what happens in your failing case. Here is what the HTML looks like after you press the button, notice the mismatch panel-danger vs. panel-default:
Use an interpolated expression in the class attribute, for example:
class="{{!ctrl.valid?'notValid':'valid'}}"
I have the following in to show and hide the clear button based upon if the searchQuery is empty or not. When a user starts typing in the input box, the button shows instantly.
However, when the user either clicks the clear button or deletes all input, there is a noticeable lag before the clear button is removed. I have tried ng-show as well, and have received the same results. Any ideas why this lag might exist?
HTML
<button ng-if="search.cardsQuery.length" class="button-icon" ng-click="clearSearchQuery()">
<i class="ion-android-close search-cards"></i>
</button>
CONTROLLER
$scope.clearSearchQuery = function() {
$scope.search.cardsQuery = '';
};
Check the css class on the element you're applying ng-if/ng-show to. Look for the transition effect. If the class has a transition, it may be the cause to the delay:
.button-icon {
transition: all .5s;
}
Its a common problem seen among the developers. Even trying with ng-if causes the same issue. I can suggest a simple solution for you.
Open your css file for the particular html file and add below line.
**.ng-hide { display: none !important }**
Hope, it will help.
$scope.$evalAsync();
Worked for me :)
As far as I know angular doesn't link hidden HTML elements, so I assume when the viewport width is 500px or larger, the first paragraph is not linked (the mydirective link function is not triggered).
<p mydirective>{{content | customFilter}}<p>
<p mydirective>{{content}}<p>
p {
display:block;
}
#screen and min-width:500px {
p:nth-child(1) {
display:none;
}
}
However, the filtering function is still triggered as well as binding function for mydirective. Is there any way to prevent angular from triggering filter function and binding function for hidden HTML elements?
The task here for me is to show filtered data for small screens (less than 500px) and unfiltered data for larger screens.
Instead of using CSS to hide and show elements, use ng-if which will then remove the elements from the DOM and therefore prevent any Angular related magic happening for those elements (Until you want them back again).
When I click an element, I'd like another element to first fade out, and then be set to display: none.
I have the following code:
Partial:
<div class="main_menu_image" ng-class="{ fadeOut : MenuOpen==true }" /></div>
<div class="button" ng-click="ActivateMenu()"></div>
Then in my controller:
$scope.MenuOpen = false;
$scope.ActivateMenu = function(){
$scope.MenuOpen = $scope.MenuOpen === false ? true: false;
}
So when I click the button, element main_menu_image gets the class fadeOut. So it now fades out. But after the fading animation completes I would also like to set display to none on main_menu_image so it is completely hidden.
I don't want to resort to jQuery. Is there an Angular approved way of doing this?
Yes it's very easy to do:)
Like Svein says, you can use ng-show, and you can use ng-hide.
Working fiddle here
This hides things instantly though. But you can for example set a timeout, via the $timeout service, and set your hiding boolean in that way.
You can also use ng-if, this actually removes the element from the DOM if the condition is not met, rather than just setting display:none.
Update: Here's a more proper fiddle showcasing what you're trying to do
You can use ngShow. If you use the ngAnimate module, you'll have built in support for animations for most built-in Angular directives.
See here for more information:
https://docs.angularjs.org/guide/animations