ngx-joyride not showing when click on button - angular9

I have implemented ngx-joyride for the demo purpose of my website.
But it is not showing anything when clicking on the button (joyride is button).
I am attaching the screenshot of my angular 9 browser console and webpage so that you can get better idea.
Please help me to resolve the issue. Thanks in advance.
//Angular 9 code
import {
Component,
OnInit,
ElementRef,
ViewChild,
AfterViewInit,
} from "#angular/core";
import { JoyrideService } from "ngx-joyride";
#Component({
selector: "app-temporary",
templateUrl: "./temporary.component.html",
styleUrls: ["./temporary.component.scss"],
})
export class TemporaryComponent implements OnInit, AfterViewInit {
constructor(private joyride: JoyrideService) {}
#ViewChild("ele1", { static: false }) ele1: ElementRef;
#ViewChild("ele2", { static: false }) ele2: ElementRef;
ngOnInit(): void {}
ngAfterViewInit() {
console.log("1", this.ele1);
console.log("2", this.ele2);
}
//ngx-joyride-tour
onClick() {
// alert("coming here 1");
console.log("joyrideService", this.joyride);
this.joyride
.startTour({ steps: ["ONE", "TWO"], logsEnabled: true })
.subscribe(
(step) => {
console.log("coming step section");
console.log(step);
},
(error) => {
console.log("coming in error section");
},
() => {
console.log("tour finished");
}
);
}
}
<div>
<button class="btn btn-sm btn-primary" (click)="onClick()">joyride</button>
<div joyrideStep="ONE" title="Page Title" text="Main title!" #ele1>Text</div>
<div joyrideStep="TWO" title="Page Title" text="Main title!" #ele2>Div content</div>
</div>
<h1>Temporary PAge</h1>

There were mistaken by us we have not added a joyride module with forChild() in lazy loaded modules.

Related

Angular: sanitizer.bypassSecurityTrustHtml does not render attribute (click)

I try to render a button and it works fine, but when I click the button it doesn't execute alertWindow function, help!:
app.component.ts:
import {
Component,
ElementRef,
OnInit,
ViewEncapsulation } from '#angular/core';
import { DomSanitizer, SafeHtml } from "#angular/platform-browser";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
encapsulation: ViewEncapsulation.ShadowDom,
})
export class AppComponent implements OnInit {
public content: SafeHtml;
constructor(private sanitizer: DomSanitizer) {}
async ngOnInit() { this.renderButton(); }
alertWindow() { alert("don't work"); }
renderButton() {
this.content =
this.sanitizer.bypassSecurityTrustHtml(`
<button (click)='connectWallet()' class="button">
Connect your wallet
</button>`);
}
app.component.ts;
<div [innerHTML]="content"></div>
Solution
Based on what I understand you wanted to display HTML dynamically at runtime? then solution is to use
ComponentFactoryResolver
and ViewContainerRef
It will be better if you can provide more details, what you are trying to achieve, so that people can guide you
Why it didn't work?
It doesn't work because it is outside of angular, when you use innerHTML then whatever you passed to it is pure vanilla HTML and JavaScript
Try this example
(window as any).alertWindow = function () {
alert("don't works");
};
#Component({...})
export class AppComponent {
...
renderButton() {
this.content = this.sanitizer.bypassSecurityTrustHtml(`
<button onclick='alertWindow()' class="button">Connect your wallet</button>
`);
}
}
It works right?
As you can see I have moved alrertWindow function outside of component's class and added to window variable and also changed (click) to onclick

How to make the creation of a card dynamic?

My Problem is that every template created will be Added to the same Card like the image below shows it
And if i set the height rather than auto it will cut the card until the giving measurement.
is there anyone who can help me to make each template have it own card ?
Card.Html
<div class="content" >
<div fxLayout="row wrap" fxLayoutGap="16px grid">
<div [fxFlex]="(100/gridColumns) + '%'" fxFlex.xs="100%" fxFlex.sm="33%" >
<mat-card class="mat-elevation-z4 info" >
<mat-card-content *ngFor="let item of templates" [innerHTML]="item.templatebody | safeTemplate"></mat-card-content> <!-- named one way flow syntax property binding-->
</mat-card>
</div>
</div>
</div>
Card.ts
import { Component, OnInit, ViewChild,Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from "#angular/platform-browser";
import { EmailEditorComponent } from 'angular-email-editor';
import { SenderService } from "../sender.service";
import { TemplateCard } from "src/app/layouts/default/templates/template";
//this pipe is designed to make the HtmlRender Safe using SanitizerDOM
#Pipe({ name: "safeTemplate" })
export class SafeHtmlPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) {}
transform(value: any) {
return this.sanitizer.bypassSecurityTrustHtml(value);
}
}
#Component({
selector: 'app-cards',
templateUrl: './cards.component.html',
styleUrls: ['./cards.component.scss']
})
export class CardsComponent implements OnInit {
public templates:TemplateCard[];
public model: any;
options = {
};
gridColumns = 3;
toggleGridColumns() {
this.gridColumns = this.gridColumns === 3 ? 4 : 3;
}
dangerousUrl='<input type="checkbox">';
constructor(public http:SenderService) { }
ngOnInit(): void {
this.model=this.http.getEmail("http://localhost:3000/savetemplate").subscribe( data => {
this.templates=data;
console.log(this.templates);
},
err => console.error(err),
() => console.log('template completed')
);}
}

Not getting popup in angular6 project

I am doing project in angular6. I have put "openModal" button. After clicking on that button popup need to be show. But I am not getting popup. But data which suppose to display on popup will getting display on same page. I am not getting where I have done mistake. Please anyone help me to find, where I have done mistake.
Here I have attached screenshot of output which I am getting.
https://imgur.com/Qjiy7jy
Here is my code
app.component.html
<button (click)="openModal()">Open Dialog</button>
app.component.ts
import { Component } from '#angular/core';
import { MatDialog, MatDialogConfig } from '#angular/material';
import { MyDialogComponent } from './my-dialog/my-dialog.component';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(public dialog: MatDialog) { }
openModal() {
console.log("calling");
const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = {
id: 1,
title: 'Angular For Beginners'
};
const dialogRef = this.dialog.open(MyDialogComponent, dialogConfig);
dialogRef.afterClosed().subscribe(result => {
alert("response: " + result)
});
}
}
my-dialog.component.html
<p>
my-dialog works!
</p>
my-dialog.component.ts
import { Component, Inject } from '#angular/core';
import { MAT_DIALOG_DATA } from '#angular/material';
import {MatSelectModule} from '#angular/material/select';
import {FormControl, Validators} from '#angular/forms';
import {MatInputModule} from '#angular/material'
export interface Staff {
name: string;
}
#Component({
selector: 'app-my-dialog',
templateUrl: './my-dialog.component.html',
styleUrls: ['./my-dialog.component.css']
})
export class MyDialogComponent {
modalTitle: string;
constructor(#Inject(MAT_DIALOG_DATA) public data: any) {
this.modalTitle = data.title;
console.log(data)
}
staffControl = new FormControl('', [Validators.required]);
selectFormControl = new FormControl('', Validators.required);
}
add in your module
entrycomponent:[yourdailogComponent]
and import css in your style.css
#import '~#angular/material/prebuilt-themes/indigo-pink.css';
openHashTagDialog() {
const dialogRef = this.dialog.open(AddHashTagdialogComponent, {
data: '',
width: '400px'
});
dialogRef.afterClosed().subscribe(result => {
this.fetchHashTagsList();
});
}

How to use one component data in another component in angular 6?

I have a component.ts file which is making a http call & retrieving json data as response. I need to use this response in another component.ts file. Can anyone tell me how to process this?
first component.ts:
#Component({
selector: 'app-cat',
templateUrl: './first.component.html',
styleUrls: ['./first.component.css']
})
export class firstComponent extends Lifecycle {
this.http.get('/name',{responseType:"json"}).subscribe(
response => {
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
});
}
I need to use the json content which is in the response in my second component file. Can anybody tell me how to proceed this in angular6?
****Create separate service for making calls and in that service create a method as such
public getData(): Observable<> {
return this.http.get('/name',{responseType:"json"}).subscribe(
response => {
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
});
}
****And in your component declare service in constructor //don't forget to import it
public jsonData:any;
constructor(private Service: Service ) {
}
getData() {
this.Service.getData().subscribe(data => {
console.log("Data is ",data);
this.jsonData = data;
},
error => console.log(error)
);
}
Finally,you can use jsonData to work with your data.
Parent to Child: Sharing Data via Input
parent.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-parent',
template: `
<app-child [childMessage]="parentMessage"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent{
parentMessage = "message from parent"
constructor() { }
}
child.component.ts
import { Component, Input } from '#angular/core';
#Component({
selector: 'app-child',
template: `
Say {{ message }}
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
#Input() childMessage: string;
constructor() { }
}
Sharing Data via Output() and EventEmitter
parent.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-parent',
template: `
Message: {{message}}
<app-child (messageEvent)="receiveMessage($event)"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
message:string;
receiveMessage($event) {
this.message = $event
}
}
child.component.ts
import { Component, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-child',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message: string = "Hola Mundo!"
#Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
please visit https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/ for other methods.
Solution 1 using a common injectible service
Shared.service.ts
#Injectible()
class SharedService {
function getData():any{
return this.http.get('/name',{responseType:"json"}).subscribe(
response => {
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
});
}
}
Solution 2 using a parent child component
Second.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-first-component',
template: `<p>{{data}}</p>`
})
export class SecondComponent{
data:any={};
ngOnInit(){this.getData();}
function getData():any{
this.http.get('/name',{responseType:"json"}).subscribe(
response => {
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
this.data=data
});
}
}
parent.component.ts
import { Component } from '#angular/core';
import { SecondComponent } from './second.component';
#Component({
selector: 'app-first-component',
template: `
<h3>Get data (via local variable)</h3>
<button (click)="second.getData()">GetData</button>
<app-first-component #second></app-first-component>
`
})
export class FirstComponent{ }
Use Input & Output Decorators
Basic concept ---> DEMO
app.component.html:
<app-component1 (elm)="catch1Data($event)">
</app-component1>
<app-component2 [elm]="datatocomp2" *ngIf="datatocomp2"></app-component2>
parent component : {{datatocomp2 | json}}
app.component.ts:
datatocomp2: any;
catch1Data(data) {
console.log(data)
this.datatocomp2 = data;
}
component1.ts:
#Output () elm : EventEmitter<any> = new EventEmitter<any>();
objectData: any;
constructor() { }
ngOnInit() {
let objectData = {
comp: 'component 1',
data: 'anything'
}
this.objectData = objectData;
this.elm.emit(objectData)
}
component2.ts:
#Input() elm: any;
constructor() { }
ngOnInit() {
console.log(this.elm);
}
You can create store service for your 'global' data:
store.service.ts
import { Injectable } from '#angular/core';
#Injectable()
export class StoreService {
protected store: Map<string, any> = new Map();
constructor() { }
public get(key: string): any {
return this.store.get(key);
}
public set(key: string, value: any) {
this.store.set(key, value);
}
}
And then in yours component (lets call it X) you save data to store:
x.component.ts
import { Component, OnInit } from '#angular/core';
import { HttpClinet } from '#angular/common/http';
import { StoreService } from './store-service.service.ts';
#Component({
selector: 'app-x',
templateUrl: './x.component.html',
styleUrls: ['./x.component.css']
})
export class XComponent implements OnInit {
constructor(
private store: StoreService,
private http: HttpClient,
) { }
ngOnInit() {
}
getResource() {
this.http.get('/name',{responseType:"json"}).subscribe(
response => {
this.store.set('response', response);
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
});
}
And then in yours other component (lets call it Y) you get your data:
y.component.ts
import { Component, OnInit } from '#angular/core';
import { StoreService } from './store-service.service.ts';
#Component({
selector: 'app-y',
templateUrl: './y.component.html',
styleUrls: ['./y.component.css']
})
export class YComponent implements OnInit {
constructor(
private store: StoreService
) { }
ngOnInit() {
}
getSavedResponse() {
// ask store for the resource
return this.store.get('response');
});
}
This is just simple example, if you know the structure of your response got by http call it would be good idea to make model of it.
Using the store any component can get or set store data.
If you need something more complex look for: #ngrx/store
Cases when you would not need store service:
If you do that http call in parent component then you can use child inputs to pass the data.
If you make that call in child component then use #Output and EventEmitter, to pass up the data (just one level, you can not do this to pass to grandparent)
Regards.

Dynamic tab navigation system using Angular 2

I want to create a dynamic tabs navigation system using Angular 2.
Basically I want to first display a single tab that contains a single component, containing clickable objects (like links, buttons...).
I would like that a click on one of those links adds a new tab, and that a click on each tab (the initial one and the newly created tab) displays a corresponding component in display zone (router-outlet) below.
This is what I've tried so far:
app.component.ts (Root component and "tabs container):
import { Component, OnInit } from '#angular/core';
import { TabComponent } from './tab/tab.component';
import { FirstComponent } from './test/first.component';
import { SecondComponent } from './test/second.component';
import { ThirdComponent } from './test/third.component';
import { ROUTER_DIRECTIVES } from '#angular/router';
#Component({
selector: 'my-app',
templateUrl: './app/app.component.html',
directives: [TabComponent, ROUTER_DIRECTIVES, FirstComponent, SecondComponent, ThirdComponent],
})
export class AppComponent implements OnInit{
tabList: any[];
constructor() {}
ngOnInit() {
this.tabList = [
{
name: 'link 1',
link: "/comp1"
},
{
name: 'link 2',
link: "/comp2"
},
{
name: 'link 3',
link: "/comp3"
}
]
}
}
app.component.html:
<h1>Tabs container</h1>
<div>
<nav>
<tab *ngFor="let tab of tabList" [name]="tab.name" [link]="tab.link"></tab>
</nav>
</div>
<div>
<router-outlet></router-outlet>
</div>
Each tab is represented by a tab.component.ts:
import { ROUTER_DIRECTIVES, Router } from '#angular/router';
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'tab',
templateUrl: './app/tab/tab.component.html',
directives: [ROUTER_DIRECTIVES]
})
export class TabComponent implements OnInit {
#Input() name: string;
#Input() link: string;
#Input() param: string;
targetArray: Array<any>;
constructor(private router: Router) {}
ngOnInit() {
}
}
which template is tab.component.html:
<a [routerLink]='link'>{{name}}</a>
Here is the app.routes.ts file:
import { provideRouter, RouterConfig } from '#angular/router';
import { TabComponent } from './tab/tab.component';
import { FirstComponent } from './test/first.component';
import { SecondComponent } from './test/second.component';
import { ThirdComponent } from './test/third.component';
export const routes: RouterConfig = [
{
path: '',
component: TabComponent
},
{
path: 'comp1',
component: FirstComponent
},
{
path: 'comp2',
component: SecondComponent
},
{
path: 'comp3',
component: ThirdComponent
},
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];
Here is for example the first.component.ts (SecondComponent and ThirdComponent are similar):
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'first',
template: `<h1>First</h1>
<button (click)="addTab()">Display child</button>
`
})
export class FirstComponent implements OnInit {
constructor() {}
ngOnInit() {
}
addTab(){
}
}
I would like to put the tab creation logic in the addTab() method to basically add an element to the tabList array in app.component.ts and obtain the desired behavior but I don't know how to transfer data from this component to the app.component.ts.
I also open to any different approach and suggestions.
You can inject the Router into your component and use the config method to configure dynamic links.
router.config([
{ 'path': '/', 'component': IndexComp },
{ 'path': '/user/:id', 'component': UserComp },
]);
The documentation for the Router service can be found here.