How do i use animation in Angular2 for Router Compoenents - animation

I want to animate in and out my components when the active router link changes. How do I write the code the animation code so that when the router changes, a component fades out then another fades in?
The code that I've been trying is the following.
#Component({
selector: 'app-component',
templateUrl: './component.component.html',
animations: [trigger(
'openClose',
[
transition(":enter", [
style({ opacity: 0 }),
animate('2000ms', style({ opacity: 1 }))
]),
transition(":leave", [
animate('2000ms', style({ opacity: 0 }))
])
])]
})
But I think I got the concept wrong, as I'm trying to use that piece of code in at least 2 components but none of them is fading in or out.
Is this possible to do with this function or am i tackling the issue with a wrong manner?

Example with Angular 4
Here's how I implemented a fade in animation on my home component route
import { Component } from '#angular/core';
import { fadeInAnimation } from '../_animations/index';
#Component({
moduleId: module.id.toString(),
templateUrl: 'home.component.html',
animations: [fadeInAnimation],
host: { '[#fadeInAnimation]': '' }
})
export class HomeComponent {
}
This is the animation defined in a separate file
import { trigger, state, animate, transition, style } from '#angular/animations';
export const fadeInAnimation =
trigger('fadeInAnimation', [
// route 'enter' transition
transition(':enter', [
// styles at start of transition
style({ opacity: 0 }),
// animation and styles at end of transition
animate('.3s', style({ opacity: 1 }))
]),
]);
For other animations and a live demo you can check out this post

Your code seems correct to me, you just need to bind the animation to a component. There are two ways:
Add it to your template, for example to a div:
<div class="container" [#openClose]="'true'">
...
</div>
Or directly apply it to your host component (<app-component>):
#Component({
selector: 'app-component',
templateUrl: './component.component.html',
animations: [trigger(
'openClose',
[
transition(":enter", [
style({ opacity: 0 }),
animate('2000ms', style({ opacity: 1 }))
]),
transition(":leave", [
animate('2000ms', style({ opacity: 0 }))
])
])],
host: {
'[#openClose]': 'true',
'style': 'display: block;'
},
})
The animation works by component, so you need to declare the animation on both of them.
The leave animation may not be noticed on state change. The official documentation has an example on how to use animations in route components
Hope it helps!

Related

Webchat: unable to render new elements using activitymiddleware in combication with grouping of avatars

I am not able to add new elements to webchat using activitymiddleware since the update to 4.14. As an example I added some code I use for typing indicators. As soon as I do that, the grouping of my avatar does not work anymore.
Without activitymiddleware and showAvatarInGroup: 'sender' -> normal behavior. Avatar is shown once per group of messages as well as the timestamp.
With activitymiddleware and showAvatarInGroup: 'sender' -> typing indicators are rendered as expected, timestamps are shown (but not grouped) and the Avatar is not shown at all.
With activitymiddleware and showAvatarInGroup : 'group' -> typing indicators are rendered as expected and the Avatar as well as the timestamps are shown. But not grouped.
Botcode (Node)
The bot sends an event to ask the webchat client to render an element. In this case a typing indicator but it could also be a new inputform.
await context.sendActivity({ name: 'typingIndicator', type: 'event' });
The webchat code (React) has an activitymiddleware to render this typing indicator as soon as the event is in:
import React, { useEffect, useMemo } from 'react';
import ReactWebChat, { createDirectLine } from 'botframework-webchat';
import TypingIndicator from './TypingIndicator';
const WebChat = ({ className, onFetchToken, store, token }) => {
const directLine = useMemo(() => createDirectLine({ token }), [token]);
const activityMiddleware = () => next => ({ activity, nextVisibleActivity, ...otherArgs }) => {
const { name, type } = activity;
// first remove all existing typing indicators
let elements = document.getElementsByClassName('typing-indicator');
for (let i = 0; i < elements.length; i++) {
elements[i].style.display = 'none'
}
// if we reveive a typing event, render a typing Indicator
if (type === 'event' && name === 'typingIndicator') {
return () => <TypingIndicator activity={activity} nextVisibleActivity={nextVisibleActivity} />;
} else {
return next({ activity, nextVisibleActivity, ...otherArgs });
}
}
const styleOptions = {
botAvatarInitials: 'Max',
showAvatarInGroup: 'sender', // group works ok
botAvatarImage: `${process.env.REACT_APP_AVATAR_URL}`,
}
useEffect(() => {
onFetchToken();
}, [onFetchToken]);
return token ? (
<ReactWebChat className={`${className || ''} web-chat`} directLine={directLine} activityMiddleware={activityMiddleware} store={store} styleOptions={styleOptions}/>
) : (
<div className={`${className || ''} connect-spinner`}>
<div className="content">
<div className="icon">
<span className="ms-Icon ms-Icon--Robot" />
</div>
<p>Connecting.</p>
</div>
</div>
);
};
export default WebChat;
The typing indicator
import './TypingIndicator.css';
import React from 'react';
const {
hooks: { useRenderActivityStatus }
} = window.WebChat;
const TypingIndicator = ({ activity, nextVisibleActivity }) => {
const renderActivityStatus = useRenderActivityStatus({ activity, nextVisibleActivity });
return (
<div>
<div className="typing-indicator">
<span></span>
<span></span>
<span></span>
</div>
{renderActivityStatus()}
</div>
);
};
export default TypingIndicator
And its styling
.typing-indicator {
background-color: transparent;
height: 35px;
width: 60px!important;
border-radius: 20px;
padding:10px;
margin-left: 65px;
}
.typing-indicator span {
line-height: 35px;
display:inline-block;
vertical-align: middle;
height: 10px;
width: 10px;
margin: 0 1px;
background-color: #9E9EA1;
border-radius: 50%!important;
opacity: 0.4;
animation: bounce 0.7s linear infinite;
}
.typing-indicator span:nth-child(1)
{
animation-delay: 0.1s;
}
.typing-indicator span:nth-child(2)
{
animation-delay: 0.2s;
}
.typing-indicator span:nth-child(3)
{
animation-delay: 0.1s;
}
#keyframes bounce {
30% { transform: translateY(-4px); }
60% { transform: translateY(0px); }
80% { transform: translateY(4px); }
100% { transform: translateY(0px); opacity: 0.5; }
}
"dependencies": {
"botframework-webchat": "^4.14.0",
"react": "16.12.0",
"react-dom": "16.12.0",
"react-scripts": "^3.4.1",
},
The problem was caused by the order in which I sent activities from the bot to webchat. I used to send:
typing-indicator event
message event
typing-indicator event
message event
The activity middleware would see the typing indicator event and replace the default render ('void') with a new rendering (my typing indicator).
My assumption is that the next event (the message) will be rendered without an avatar because webchat is already under the assumption that an avatar has been rendered.
To bypass this behavior my solution was to send
message event
typing-indicator event
message event
From a Ux perspective not such a bad idea and the problem does not occur

Styling cannot be applied to button - React Hooks

I'm using a resuable component for button wherein i wanna pass the color and bgColorvia props, color gets applied but then the background color doesnt apply
const useStyles = makeStyles(theme => ({
button: {
//width:'100%',
margin: theme.spacing(1)
},
input: {
display: "none"
}
}));
export default function ContainedButtons(props) {
const classes = useStyles();
const btnStyle = {
color: props.color,
backgroundColor: props.bgClrRed
};
console.log(props);
return (
<div>
<Button
variant="contained"
style={{ backgroundColor: props.bgClrRed, color: props.color }}
fullWidth="true"
className={classes.button}
>
{props.name}
</Button>
<Button
variant="contained"
style={btnStyle}
fullWidth="true"
className={classes.button}
>
{props.name}
</Button>
</div>
);
}
I'm missing something I don't know what can anyone please lemme know
Updates
import ContainedButtons from '../container/buttonsControl';
import css from '../variable.scss';
Try a spread operator:
style={...btnStyle}

Setting width of Image in CKEditor 5

I have a page where I use CKEditor 5 with CKFinder 3.
By default, the images that are included in the textarea are responsive and can only be aligned as full or right.
The concerning page has photos of contacts on it and they shouldn't be that big.
How can I configure the width of an image that is inserted through the button of the toolbar?
ClassicEditor
.create( document.querySelector( '#pageTextArea' ), {
image: {
styles: [ { name: 'contact', icon: 'right', title: 'My contact style', className: 'my-contact-side-image' } ]
}
ckfinder: {
uploadUrl: 'example.com/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json'
}
})
.catch( error => {
console.error( error );
process.exit(1);
});
To provide some custom image styling you need to:
First, configure the image.styles option.
ClassicEditor.create( element, {
// ...
image: {
// ...
styles: [
// Pottentially some other style can go here. E.g. the `full` or `side`.
{ name: 'contact', icon: 'right', title: 'My contact style', className: 'my-contact-side-image' }
]
}
}
And secondly, make the image 100px wide via CSS:
.ck-content figure.image.my-contact-side-image {
float: right;
width: 100px;
}
Note that you need to handle styles of the created content outside of the editor as well.

CKEditor 5 fails to compile svg's inside Angular 5 component

I am trying to integrate CKEditor version 5 into Angular 5 application. I created a component and imported required packages. I can compile perfectly fine CKEditor using Webpack using same code, however I fail todo so inside Angular. I get weird parser error for svg paths.
Error Screenshot:
https://www.dropbox.com/s/xwoas03fd4q7gks/Screenshot%202017-12-13%2011.55.45.png?dl=0
My Component looks like:
import { Component, AfterViewInit, ChangeDetectionStrategy, ViewChild, ElementRef, ViewEncapsulation, Input, Output, EventEmitter } from '#angular/core';
// Required Dependencies for library construction
import ClassicEditor from '#ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Essentials from '#ckeditor/ckeditor5-essentials/src/essentials';
import Paragraph from '#ckeditor/ckeditor5-paragraph/src/paragraph';
import Bold from '#ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '#ckeditor/ckeditor5-basic-styles/src/italic';
import BlockQuote from '#ckeditor/ckeditor5-block-quote/src/blockquote';
import Link from '#ckeditor/ckeditor5-link/src/link';
import List from '#ckeditor/ckeditor5-list/src/list';
import Heading from '#ckeditor/ckeditor5-heading/src/heading';
import GFMDataProcessor from '#ckeditor/ckeditor5-markdown-gfm/src/gfmdataprocessor';
#Component({
changeDetection: ChangeDetectionStrategy.Default,
encapsulation: ViewEncapsulation.None,
selector: 'ten-ckeditor',
styleUrls: ['./ckeditor.component.scss'],
templateUrl: './ckeditor.component.html',
})
export class CkeditorComponent implements AfterViewInit {
#Input() content: string;
#Output() contentEdited: EventEmitter<string>;
#ViewChild('editor') editor: ElementRef;
constructor() {
}
ngAfterViewInit() {
function Markdown( editor ) {
editor.data.processor = new GFMDataProcessor();
}
console.log(List);
ClassicEditor.create(this.editor.nativeElement, {
plugins: [
Markdown,
Essentials,
Paragraph,
Bold,
Italic,
Heading,
BlockQuote,
Link,
List
],
toolbar: [
'headings',
'bold',
'italic',
'blockquote',
'link',
'numberedList',
'bulletedList'
]
})
.then(editor => {
console.log('Editor was initialized', editor);
editor.setData(this.content);
})
.catch(error => {
console.error(error.stack);
});
}
}
This is what I get when I inspect HTML inside application when I target Icon.
<svg class="ck-icon" viewBox="0 0 20 20"><body><parsererror style="display: block; white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black"><h3>This page contains the following errors:</h3><div style="font-family:monospace;font-size:12px">error on line 1 at column 1: Document is empty
</div><h3>Below is a rendering of the page up to the first error.</h3></parsererror></body></svg>
My icons weren't working either. I had something like this in my webpack config:
{
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader'
},
],
},
}
So I removed the '|svg' part, and then added:
{
test: /\.svg(\?.*)?$/,
loader: 'raw-loader',
},
And it works for me.

angular 2 img width sets to 0

So I am setting the image source and width dynamically in my template. The problem I see is that it sets the width to 0.
The template looks like:
<img src="{{item.msg}}" width="{{item.width}}" style="float:right" *ngIf="item.templateType == 'image'" />{{item.width}}
The value is passed as below from .ts
this.items.push(new ImageMessage('http://someimage.png', '100%'));
What I see is that it does not display the image but prints the value of item.width correctly. Looking into inspector it shows the width is set to 0 which explains why image is not appearing.
However, I am failing to understand why the width is getting set to 0 in img tag.
Please help.
Thanks.
You can set the width as a percentage using one-way binding syntax [style.width.%] targeting the style attribute binding of an element like <img /> in your example. HTML5 does require that the width property is in pixels, so using the [style.width.%] attribute binding would allow you to set the width as a percentage.
You're ImageMssage object would need to have the percentage '%' character removed from the width value of the ImageMessage object to make this work. With this syntax, it's flexible to work with either strings or numbers. Either '100' or 100 would work.
import {Component, NgModule} from '#angular/core'
import {BrowserModule} from '#angular/platform-browser'
import {CommonModule} from '#angular/common';
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<div *ngFor="let item of items">
<img [src]="item.msg" [style.width.%]="item.width" style="float:right;" />
</div>
</div>
`,
})
export class App {
name:string;
items: any[];
constructor() {
this.items = [
{ msg: 'http://placehold.it/800', width: '100' },
{ msg: 'http://placehold.it/800', width: '75' },
{ msg: 'http://placehold.it/800', width: 50 },
{ msg: 'http://placehold.it/800', width: '25' }
];
}
}
#NgModule({
imports: [ BrowserModule, CommonModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
If you want to set the pixels, you can use the following:
<img [src]="item.msg" [style.width.px]="item.width" ... />{{item.width}}px
Here is a plunker demonstrating the functionality.
Hopefully this helps!
I think it may set the width to 0 because you have have 100% in single quotation marks. As in { width: '100%' } try removing the quotation marks to produce { width: 100% }. This may also explain why it prints the value of item.width.

Resources