In short, I am trying to trigger a change detection loop between renderer.removeStyle and renderer.addStyle.
The style I am adding is an css animation. When it's removed and added in the same change detection loop Angular won't detect that something changed (for the same animation name).
More Details
Let's say I have a button event (click)="addAnimation('animation1')" that should add existing animation and add the new animation named animation1, animation2 ....
Of course the following code won't work:
addAnimation(animationName: string): void {
this.renderer.removeStyle(this.animate.nativeElement, 'animation');
// setTimeout(() => {
this.renderer.setStyle(this.animate.nativeElement, 'animation', animationName)
// }, 0);
}
since removing and adding a style under angular nose won't trigger any change.
One possible solution is adding a timeout (like the commented code above, but it has side effects that I am not interested in, and also the code is a little wired.
I was hoping to solve it by adding something like this.appRef.tick(); in between to force angular create another change detection loop.
That doesn't work, what am I missing? any suggestions how to do that correctly?
Thanks!
Try following way.
isClick=false;
onClick(){
isClick=true;
}
<div [ngClass]="{'yourCSSClass': isClick}">
Related
I have a very niche use-case. I have to add a modal animation like this:
regular css animation
But I need to have a component (our own filter component for a datatable) inside said modal.
So I need to use the ModalService. But this service is only attaching my custom config like this:
toggleFilter = () => {
const modalOptions: ModalOptions = {
initialState: {
labels: this.datatableLabels, // needed for filter to have labels
filterGroups: this.filterGroups // needed to add filterGroups
},
class: 'filter-modal' // this sould be my custom class
};
this.bsModalRef = this.modalService.show(FilterComponent, modalOptions);
}
to modal-content and the above mentioned animation and styling uses divs above that. Not only it's working when encapsulation set toViewEncapsulation.None then it screws our other modals as well, since I cannot apply correct classes to the one I need to mess with.
How can I overcome this issue I'm having?
Instead of using the ModalService and open desired embedded component within the modal. You can basically inject the desired component into the body of the modal while using directive instead -> Here you are declaring the whole modal layout -> you can modify all the related classes so it's easier to modify a modal and have your ViewEncapsulation untuched so other modals are unaffected.
I'm trying to implement a mask over my GoJS diagram when a details sidepanel is shown. This requires stopping propagation of click events to diagram parts beneath. How can I verify that the event target is the picture part and not the mask element which overlays it?
I've tried using the pointer-events CSS property, but that doesn't do the job.
Simplified markup:
<div id="diagramWrapper"></div>
<div id="sidebar-mask"></div>
Script snippet:
buildGo(go.Picture, {
source: 'images/icons/simplify-icon.png',
...,
click: function (e, node) {
if (e.diagram === node.part) { <-- this, right here, isn't right
let nodesToRemove = getLinkedNodes(e, node.part.data.key);
removeNodes(nodesToRemove);
}
}
})
I haven't gotten my head around the two-letter object properties that GoJS uses, which prevents me from easily finding the right property. Any insight into that would help greatly.
I suggest that you just set Diagram.isEnabled to false when you show a modal dialog. Be sure to set it back to true when the modal UI goes away for any reason. More possibilites are listed at https://gojs.net/latest/intro/permissions.html.
As documented at https://gojs.net/latest/intro/index.html#DevelopingYourDiagram, you should only be using documented API names in your code -- not the minified two character names which will change with each build.
I'd like to have a component, I called it information-board, to animate away after some seconds. I had the idea to make it slide up as exit-animation.
My approach for this is quite simple, since I can do this with css-animations regarding to this thread: Angular 2 Slide Up and Down Animation
My scss-file is looking quite simple:
.info-board {
transition: height 1s;
overflow: hidden;
}
The problem arises in the sentence from the mentioned thread: The height set to 'auto' can't be animated. This makes sense, I guess, but causing me a heap of trouble, because my information-board should be a shared component and also be allowed to be invisible at the start, only being shown when something interesting happens.
So, looking at my component-html:
<div *ngIf="informationMessage">
<div #contentElement class="info-board" [style.height]="contentHeight">
<alert type="{{alertType}}">
<strong>{{ informationHeading }}</strong> {{ informationMessage.messageText }}
</alert>
</div>
</div>
Nothing too fancy: If the informationMessage, a simple dto, is set, it should be shown. I set the height via binding in order to animate it properly.
Now the complicated part: If the info-board is not shown at the beginning, I basically need to wait for the dto to be set AND the html to be rendered. The only hook I found so far is the "afterViewChecked" one, leading to this Code:
#ViewChild('contentElement') public contentElement: ElementRef;
ngAfterViewChecked(): void {
this.checkSetBoardSize();
}
private checkSetBoardSize() {
if (this.contentElement && this.contentElement.nativeElement) {
this.contentHeight = this.contentElement.nativeElement.scrollHeight + 'px';
}
}
This event is the only one I can be sure, that the ViewChild is set, but it seems to be too late: Since this is the last step of the changetracking-logic, the height I set is ignored.
The only other hook, which looked helpful was "ngAfterContentChecked", but in this one, the ViewChild is not set.
I also didn't find a possibility to 'retrigger' the changetracking nor did the approach on Angular 2 #ViewChild in *ngIf with ViewChildren work for me.
Am I missing some sort of possibility? I know, that working with the nativeElements isn't a good idea, but from my research, this is currently needed working with heights.
You could use the animation feature of Angular, the example for ur case can be found in the angular docs
Sidenote: Be aware that the usage of the animation package (it's outsourced to #angular/animations) is changing in angular version >4.0.0-rc.1. For more the the changelog of angular
I'm embedding a PPT into my app, so I'd like a responsive iFrame. Can't get this working with the CSS based approached I've looked at here.
I'm thinking the best way would be just to make a simple component with height and width properties. Can I make these computed properties / observers that listen and update on the browser resize?
Or would I need to create a resize event and update the properties on the event?
A little code example would be much appreciated!
Thanks
I would recommend to use a CSS based approach, but you can use a component and use the resize event. Basically you would add the event listeners to window in your didInsertElement hook, and remove them in your willDestroyElement hook. Just use jQuery's .on() and .off().
onResize() {
// do whatever you want to calculate your values
set(this, 'my-frame-with', ...);
},
init() {
set(this, 'boundOnResize', get(this, 'onResize').bind(this));
},
didInsertElement() {
jQuery(window).on('resize', get(this, 'boundOnResize'));
},
willDestroyElement() {
jQuery(window).off('resize', get(this, 'boundOnResize'));
}
You can not use computed properties for this because they need to depend on observable properties. This will not work for plain JS properties, because this in an ember functionality. So you need to kind of wrap them like this.
I am trying to implement custom animations on a ng-repeat list. When an element is removed, all the elements that are below it go up.
This is done using a CSS animation on the transform attribute. On the beginning the element is not really removed from the ng-repeat list (there is an animation on the opacity attribute).
At one point, I should actually delete the element from the list. And, at the same time, I need to wind back the animation on the other elements, that have been artificially put too high.
Here is the HTML:
<div ng-repeat="card in cards" ng-style="shouldBeUpped ? uppedStyle : ''">...</div>
And here is the JS:
$timeout(function() {
$scope.shouldBeUpped = false;
$scope.cards.splice(index, 1);
}, 1000);
The problem is that $scope.cards.splice(index, 1); and $scope.shouldBeUpped = false; are not simultaneous. There is a small noticeable delay (maybe 20 or 30 milliseconds), that looks very bad, because in the meantime there is a blank space on the screen ($scope.shouldBeUpped = false; is rendered before $scope.cards.splice(index, 1);).
Do you know what I can do please?
I heard about ng-leave and ng-move classes, but the examples I found on the web don't work for me... (I am using Angular 1.4).
I think you problem is $timeout. You're adding 1s delay there.
I'm not sure how view could know about $scope.shouldBeUpped = false; earlier than $scope.cards.splice(index, 1); as all the changes are reflected when $scope.$apply()