Manage state of animation trigger in angular2 routing - angular2-routing

I am faceing an issue with angular2 animation. App has a guide system where User navigate from step 1 to step 2 and so on. Now i have animation on routing where my first component slide to left and second come from right side and this is same for every step, this flow works very well but i want to reverse it when user go back to previous step then i want that current component should slide to right and previous component should slide in from left side.
animation.ts
import {trigger, state, animate, style, transition} from '#angular/animations';
export const routeAnimation =
trigger('routeAnimation', [
state('void', style({position: 'absolute', width: '100%', top: '150px', left: '20px'})),
state('*', style({position: 'absolute', width: '100%', top: '150px', left: '20px'})),
transition(':enter', [
style({transform: 'translateX(100%)'}),
animate('0.5s ease-in-out', style({transform: 'translateX(0%)'}))
]),
transition(':leave', [
style({transform: 'translateX(0%)'}),
animate('0.5s ease-out', style({transform: 'translateX(-100%)'}))
])
]);
Components to animate while route
import {Component, HostBinding} from '#angular/core';
import {routeAnimation} from './animation';
import {state} from '#angular/animations';
#Component({
template: `<h1>first</h1>`,
animations: [routeAnimation]
})
export class FirstComponent {
#HostBinding('#routeAnimation') routerTransition = true;
}
#Component({
template: `<h1>second</h1>`,
animations: [routeAnimation]
})
export class SecondComponent {
#HostBinding('#routeAnimation') routerTransition = true;
}
#Component({
template: `<h1>third</h1>`,
animations: [routeAnimation]
})
export class ThirdComponent {
#HostBinding('#routeAnimation') routerTransition = true;
}
#Component({
template: `<h1>fourth</h1>`,
animations: [routeAnimation]
})
export class FourthComponent {
#HostBinding('#routeAnimation') routerTransition = true;
}
Thanks in advance.

Related

css style removes upon page refresh in vue project

When I first go to this link the header footer style is alright-
But then when I refresh or reload the page, the style is gone. How to fixed this?
Below is My router.js-
import { createWebHistory, createRouter } from "vue-router";
import Home from '../components/Home.vue';
import Organization from '../components/aboutus/Organization.vue';
const router = createRouter({
history: createWebHistory(),
base: process.env.BASE_URL,
scrollBehavior() {
return { x: 0, y: 0 }
},
routes: [
{
name:'Home',
path:'/',
component:Home
},
{
name:'Organization',
path:'/about_us/organization',
component:Organization
},
],
})
router.beforeEach((to, _, next) => {
return next()
})
// ? For splash screen
// Remove afterEach hook if you are not using splash screen
router.afterEach(() => {
// Remove initial loading
/*const appLoading = document.getElementById('loading-bg')
if (appLoading) {
appLoading.style.display = 'none'
}*/
})
export default router
Below is the main.js-
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/router'
import store from './store/index'
createApp(App).use(
router,
store,).mount('#app')

AnimeJs implementation with react doesn't work

I've implemented a simple Anime Js text animation into my react app; I have other other Anime Js projects which perform perfectly but I just don't see the issue with this one, and why it doesn't work.
TextColourChangeLoader.js
import React from 'react';
import './styles/TextColourChangeLoader.css';
import anime from 'animejs';
export default class TextColourChangeLoader extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "",
play: false
}
}
componentDidMount() {
this.setState({
text: this.props.textToRender,
play: true
})
}
componentWillUnmount() {
this.setState({
text: '',
play: false
})
}
playAnimeColourChange = () => {
if(this.state.play) {
anime({
targets: '.loader-letter',
delay: anime.stagger(100),
duration: 1000,
scale: anime.stagger(2, {easing: "easeInElastic"}),
color: '#7DE2FC',
direction: 'alternate',
easing: 'easeInOutElastic(1,.8)',
loop: true,
loopComplete: function() {
console.log('done')
}
});
}
}
render() {
this.playAnimeColourChange();
return (
<div id="loader-text-holder">
{this.state.text.split('').map((letter, i) => {
return <span id={letter === " " ? "loader-letter-space" : "loader-letter"+i} key={i} className="loader-letter text">{letter}</span>
})}
{this.playAnimeColourChange()}
</div>
)
}
}
Example.js
import React from 'react';
import './styles/ViewLoaderWithText.css';
import anime from 'animejs';
import TextColourChangeLoader from './TextColourChangeLoader';
export default class ViewLoaderWithText extends React.Component {
constructor(props) {
super(props);
this.state = {
play: false
}
}
componentDidMount() {
this.setState({
play: true
})
}
playAnime = () => {
if(this.state.play) {
let loaderAnime = anime({
targets: '.view-loader-shape',
delay: anime.stagger(100, {start: -100}),
translateY: [{value: -25, easing: 'easeInCubic'}, {value: 0, easing: 'easeOutCirc'}],
background: '#7DE2FC',
direction: 'alternate',
easing: 'easeInOutElastic(1,.8)',
duration: 1000,
loop: true,
autoplay: true
});
}
}
render() {
return (
<div id="view-loader-wrapper">
<div id="loader-shape-holder">
<span className="view-loader-shape" id="view-loader-shape1"></span>
<span className="view-loader-shape" id="view-loader-shape2"></span>
<span className="view-loader-shape" id="view-loader-shape3"></span>
<span className="view-loader-shape" id="view-loader-shape4"></span>
<span className="view-loader-shape" id="view-loader-shape5"></span>
</div>
<TextColourChangeLoader textToRender="Verifying email"/>
{this.playAnime()}
</div>
)
}
}
The anime js instance in the Example.js file works as it should; however the TextColourChangeLoader.js animation doesn't run. I've tried logging to the console each time a loop completes with the loopComplete callback option, and it shows that the loop is running however, the animation doesn't. I've also tried only running the TextColourChangeLoader.js animation, but that still doesn't work. What could be a possible explanation for this? Anything helps.
I think that doesn't work because you are trying to animate a component that had not loaded first. Remember the lifecycle flow in React, I prefer use React Hooks to solve the problem and this is the way: with the useEffect hook you pass in the animate function, in order to first render the component and then execute the function, not in the reverse order. I guess that the equivalent in class components is componentDidMount() so try to refactorize your code in order to connect the anime() with the componentDidMount. Conclusion, the main concept is first render the component and then execute the anime(). Sorry for my english level.

Trigger animation after page load in angular 8, ExpressionChangedAfterItHasBeenCheckedError

As the question suggests, I am trying to figure out a way to get an element animated after the page has been loaded. I have looked all over the place but there seem to be too many and no way to do this at the same time, I am hoping for some guidance. After the page is loaded in mobile the the logo should slowly animate towards the top-right and also scale down in size, if that makes sense.
I am looking for the Angular equivalent of $(document).ready(function() {}
As per suggestions, I have used ngAfterViewInit() but I still cannot get anything to work.
Below the index-section.component.html
<section class="index-section">
<div [#logoMoveResize]="load_completed ? 'initial' : 'end'" class="index-logo-wrapper" [class.hideOnLoad]="isTrue">
<figure>
<img src="assets/icons/logo_mobile.svg" alt="urbanwheels logo">
</figure>
</div>
<div class="index-media-wrapper">
<div class="media-container">
<iframe src="https://player.vimeo.com/video/128014070?autoplay=1&color=ffffff&title=0&byline=0&portrait=0" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe>
</div>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Itaque contra est, ac dicitis; Duo Reges: constructio interrete. Videsne quam sit magna dissensio?
</p>
</div>
</section>
And the index-section.component.ts
import { Component, OnInit, Inject, ViewChild } from '#angular/core';
import { trigger, state, animate, style, group, query, transition } from '#angular/animations';
#Component({
selector: 'app-index-section',
templateUrl: './index-section.component.html',
styleUrls: ['./index-section.component.scss'],
animations: [
trigger('logoMoveResize', [
state('initial', style({
transform: 'translateX(0%) translateY(0%) scale(1)',
})),
state('end', style({
transform: 'translateX(25%) translateY(-25%) scale(.3)',
})),
transition('initial <=> end', [animate('1s')]),
])
]
})
export class IndexSectionComponent implements OnInit {
load_completed = true;
innerWidth: any;
ngOnInit() {
this.innerWidth = window.innerWidth;
}
ngAfterViewInit() {
if ( this.innerWidth < 1000 ) {
this.load_completed = false;
}
}
}
This the error I am getting:
set a variable in component.ts
#Component({
selector: 'app-some',
templateUrl: './some.component.html',
styleUrls: ['./some.component.scss'],
animations: [
trigger('fadeInOut', [
state('void', style({
opacity: 0
})),
transition('void <=> *', animate(1000)),
]),
trigger('EnterLeave', [
state('flyIn', style({ transform: 'translateX(0)' })),
transition(':enter', [
style({ transform: 'translateX(-100%)' }),
animate('0.5s 300ms ease-in')
]),
transition(':leave', [
animate('0.3s ease-out', style({ transform: 'translateX(100%)' }))
])
])
]
})
export class SomeComponent implements OnInit {
load_completed = false;
ngOnInit(){
}
ngAfterViewInit(){
load_completed = true;
}
}
And in you component.html
<div [#fadeInOut]="load_completed"> some random element you want to animate </div>
As above example you can just animate when you need based on the condtion
This answer has provided me with info I need in regards to the question. As #Kevin LeStarge suggested my work around was:
setTimeout(()=> {
this.load_completed = true;
}, 0);
Or as #Lijo suggests using the AfterContentChecked life cycle hook:
import { ChangeDetectorRef, AfterContentChecked} from '#angular/core';
constructor(
private cdref: ChangeDetectorRef) { }
ngAfterContentChecked() {
this.cdref.detectChanges();
this.load_completed = true;
}
use ngAfterViewInit hook of angular to apply animation to the element.
I am looking for the Angular equivalent of $(document).ready(function() {}
the equivalent is
constructor(private zone: NgZone) {
this.zone.onStable.pipe(
// don't keep the stream open
first()
).subscribe(() => /* zone is stable, do something */)
}
You can use Angular Resolve - Interface that classes can implement to be a data provider. A data provider class can be used with the router to resolve data during navigation. The interface defines a resolve() method that will be invoked when the navigation starts. The router will then wait for the data to be resolved before the route is finally activated.
For more details -
https://angular.io/api/router/Resolve

Full Calendar's body is not displayed on load

I am trying to display full-calendar module in ngx bootstrap tab teg but at the beginning I am getting only header after clicking header buttons it is displaying all calendar
I have tried to move assignment in ngOnInit but it didn't work
import {AfterViewInit, Component, OnInit} from '#angular/core';
import dayGridPlugin from "#fullcalendar/daygrid";
#Component({
selector: 'app-calendar-module',
templateUrl: './calendar-module.component.html',
styleUrls: ['./calendar-module.component.scss']
})
export class CalendarModuleComponent implements OnInit, AfterViewInit {
public calendarPlugins = [dayGridPlugin];
constructor() { }
ngOnInit() {
}
ngAfterViewInit(){
}
}
<full-calendar
defaultView="dayGridMonth"
[plugins]="calendarPlugins"
[weekends]="false"
[events]="[
{ title: 'event 1', start:'2019-08-19', end:'2019-08-30', color:'red' }
]"
></full-calendar>
Link to screenshot
this worked
ngOnInit() {
setTimeout(() => {
this.calendarComponent.getApi().render();
}, 300);
}

Changing styles during clicking

I have ReactJS project and I want to change colour of button during clicking. I know that it is a Ripple API but it's very incomprehensible to use it. Could someone advise me how can I do that?
I've tried to create two elements - parent and child - and changed background of child to transparent while clicking. Unfortunately I have also 'classes' object responsible for changing class if button is active and it is just not working.
My code below:
import React, { Component } from 'react';
import { withStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import PropTypes from 'prop-types';
import styles from './MydButton.style';
class MyButton extends Component {
constructor(props) {
super(props);
this.state = {
isClicked: false
};
}
handleClick = () => {
this.setState({ isClicked: !this.state.isClicked });
}
render() {
const {
classes,
children,
color,
disabled,
className,
onClick,
type,
border,
...props
} = this.props;
const myClass = this.state.isClicked ? 'auxClass' : 'buttonDefaultRoot';
return (
<div className={classes.parentRoot} >
<Button
classes={{
root: disabled
? classes.buttonDisabledRoot
: classes.buttonRoot,
label: disabled
? classes.buttonLabelDisabled
: classes.buttonLabel,
}}
{...props}
onClick={this.handleClick}
className={myClass}
disabled={disabled}
type={type === undefined ? 'button' : type}
>
{children}
</Button>
</div>
)
}
};
MyButton.propTypes = {
children: PropTypes.string.isRequired,
disabled: PropTypes.bool,
classes: PropTypes.object.isRequired,
};
MyButton.defaultProps = {
disabled: false,
};
export default withStyles(styles)(MyButton);
and styles:
const buttonRoot = {
border: 0,
height: 48,
width: '100%',
}
export default theme => ({
buttonDefaultRoot: {
...buttonRoot,
transition: 'all 1s ease-in-out',
backgroundImage: 'linear-gradient(to right, #F59C81, #E65DA2, #E65DA2, #B13A97, #881E8E)',
boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.16)',
backgroundSize: '300% 100%',
marginTop: 0,
'&:hover': {
backgroundPosition: '100% 0%',
transition: 'all 1s ease-in-out',
}
},
parentRoot: {
...buttonRoot,
backgroundColor: 'red',
backgroundSize: '300% 100%',
marginTop: 36,
},
auxClass: {
backgroundImage: 'none',
},
Material UI Core for ReactJS
The documentation is very good. I have updated my answer to accomodate the specific needs of this question. I have also included two general solutions for anyone who stumbles upon this question.
Tailored Solution:
Changes background color of button from classes.buttonDefaultRoot (a color defined by owner of question) to the gradient defined by the owner of this question.
First step, have a variable stored in state. You can call it whatever you want, but I'm calling bgButton. Set this to this.props.classes.buttonDefaultRoot like so:
state = {
bgButton: this.props.classes.buttonDefaultRoot,
}
Next, you want to define your function that will handle the click. Again, call it what you want. I will call it handleClick.
handleClick = () => {
const { classes } = this.props; //this grabs your css style theme
this.setState({ bgButton: classes.parentRoot.auxClass }); //accessing styles
};
A couple of things are happening here. First, I am destructuring props. So, I am creating a new const variable called classes that has the same value as this.props.classes. The classes contains a set of objects that defines your css styles for your buttons, margins, etc. You can access those styles just like you would if you were trying to get the value of a prop in an obj.
In this case you can access your button style by doing, classes.buttonDefaultRoot. That takes care of your handle click function.
Last step: render the button. In your render method you want to grab your bgButton from state like so:
render() {
const { bgButton } = this.state;
Then you want to assign your className of your button to bgButton and add the onClick functionality like this (this follows the Material UI Core documentation):
<Button variant="contained" color="primary" className={classNames(bgButton)} onClick={this.handleClick}>Button Name</Button>
Putting it all together you get this:
import React, { Component } from "react";
import Button from "#material-ui/core/Button";
import PropTypes from "prop-types";
import classNames from "classnames";
import { withStyles } from "#material-ui/core/styles";
export default theme => ({ ... }) //not going to copy all of this
class MyButton extends Component {
state = {
bgButton: null
};
handleClick = () => {
const { classes } = this.props;
this.setState({ bgButton: classes.parentRoot.auxClass });
};
render() {
const { bgButton } = this.state;
return (
<div className={classes.container}>
<Button
variant="contained"
color="primary"
className={classNames(bgButton)}
onClick={this.handleClick}
>
Custom CSS
</Button>
</div>
);
}
}
MyButton.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(MyButton);
General Solution
This solution is for those who want to use the predefined colors, i.e. default, primary, secondary, inherit. This implementation does not need the PropTypes or className imports. This will change the color from the predefined blue to the predefined pink. That's it.
state = {
bgButton: "primary",
}
handleClick = () => {
this.setState({ bgButton: "secondary" });
}
render() {
const { bgButton } = this.state;
return(
...
<Button
onClick = {this.handleClick}
variant = "contained" //checked Material UI documentation
color={bgButton}
> ..etc.
General Solution 2
To accommodate your custom styles to the button, you would have to import PropTypes and classNames and take a similar approach as the tailored solution above. The only difference here will be my syntax and class name. I am closely following the documentation here so you can easily follow along and readjust where necessary.
import React, { Component } from "react";
import Button from "#material-ui/core/Button";
import PropTypes from "prop-types";
import classNames from "classnames";
import { withStyles } from "#material-ui/core/styles";
import purple from "#material-ui/core/colors/purple";
const styles = theme => ({
container: {
display: "flex",
flexWrap: "wrap"
},
margin: {
margin: theme.spacing.unit
},
cssRoot: {
color: theme.palette.getContrastText(purple[500]),
backgroundColor: purple[500],
"&:hover": {
backgroundColor: purple[700]
}
},
bootstrapRoot: {
boxShadow: "none",
textTransform: "none",
fontSize: 16,
padding: "6px 12px",
border: "1px solid",
backgroundColor: "#007bff",
borderColor: "#007bff",
fontFamily: [
"-apple-system",
"BlinkMacSystemFont",
'"Segoe UI"',
"Roboto",
'"Helvetica Neue"',
"Arial",
"sans-serif",
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"'
].join(","),
"&:hover": {
backgroundColor: "#0069d9",
borderColor: "#0062cc"
},
"&:active": {
boxShadow: "none",
backgroundColor: "#0062cc",
borderColor: "#005cbf"
},
"&:focus": {
boxShadow: "0 0 0 0.2rem rgba(0,123,255,.5)"
}
}
});
class MyButton extends Component {
state = {
bgButton: null
};
handleClick = () => {
const { classes } = this.props;
this.setState({ bgButton: classes.cssRoot });
};
render() {
const { classes } = this.props; //this gives you access to all styles defined above, so in your className prop for your HTML tags you can put classes.container, classes.margin, classes.cssRoot, or classes.bootstrapRoot in this example.
const { bgButton } = this.state;
return (
<div className={classes.container}>
<Button
variant="contained"
color="primary"
className={classNames(bgButton)}
onClick={this.handleClick}
>
Custom CSS
</Button>
</div>
);
}
}
MyButton.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(MyButton);
A tip. You no longer need a constructor or to bind methods.
Hope this helps.

Resources