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

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

Related

Detect if a boolean changes Angular 8

I have this ngbCollapse in my html:
<div style="margin: 1.5em 1.5em;" [ngbCollapse]="isCollapsed">
//things
</div>
In my component, I would call a method everytime isCollapsed changes:
export class Component implements OnInit {
public isCollapsed = true;
constructor(private Serv: _service) {}
ngOnInit() {}
//Everytime isCollapsed changes I would call this method
isCollapsedInService () {
this._service.set(isCollapsed);
}
I would suggest you use Event Binding in Angular
In Angular 8, event binding is used to handle the events raised from the DOM like button click, mouse movement etc. When the DOM event happens (eg. click, change), it calls the specified method in the component.
https://www.javatpoint.com/event-binding-in-angular-8#:~:text=In%20Angular%208%2C%20event%20binding,specified%20method%20in%20the%20component.
In html file
<button (click)="isCollapsedInService($event)">Btn</button> <!--Event Binding-->
In .ts file
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
isCollapsedInService($event){
console.log("Button is clicked!", $event);
}
}

How to get the selected value from one component to other using event emitter in angular 8

I have 2 components , one login and other home. When I change drop down into login component ,selected value need to display in home component. I am already emitting the onchange event from login component to home component and displaying the value but still I am not getting the value into home component.Here is the code below
login.component.html
<select #mySelect (change)="onOptionsSelected(mySelect.value)">
<option value="one">one</option>
<option value="two">two</option>
</select>
login.component.ts
import { Component, OnInit,Input,Output, EventEmitter } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
#Output() buttonClicked = new EventEmitter();
constructor(private router: Router) { }
#Input() item: string;
ngOnInit() {
}
onOptionsSelected(value:string){
console.log("the selected value is " + value);
this.buttonClicked.emit(value);
this.router.navigateByUrl('/home');
}
}
home.component.html
<p>home works!</p>
<app-login (buttonClicked)='showNextComponent($event)'></app-login>
<p>Hello {{ name }} </p>
home.component.ts
import { Component, OnInit,ElementRef,ViewChild } from '#angular/core';
import { CommonserviceService } from './../utilities/services/commonservice.service';
import { LoginComponent } from '../login/login.component';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
getListData: any;
constructor(private commonserviceService: CommonserviceService) { }
name:string
ngOnInit() {
}
showNextComponent(value:string) {
this.name = value;
console.log(this.name);
}
}
I pasted your code here in stackblitz: https://stackblitz.com/edit/angular-cfkqns
You are correctly emitted values up to the parent component and binding the value to be displayed in the parent component.
It is working how you expect it to :-)
UPDATE:
I have answered the same question for some one else here:
https://stackoverflow.com/a/64082745/450388
however I have updated your stackblitz to reflect how to achieve the same.
https://stackblitz.com/edit/angular-cfkqns

How to call a component from other component in angular 7

I have a checkbox,if that checkbox is checked, I need to show alert message on load the application.But problem is that checkbox is in header component and it is linked with home component.So when I will be in home page and if that checkbox is checked, I need to show alert message on load the application. Here is the code below,
header.component.html
<div><input checked type="checkbox">Other-component</div>
header.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from "#angular/router";
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor(public router: Router){}
ngOnInit() {}
}
home.component.ts
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import Speech from 'speak-tts';
import { RxSpeechRecognitionService, resultList, } from '#kamiazya/ngx-speech-recognition';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
providers: [ RxSpeechRecognitionService ]
})
export class HomeComponent implements OnInit {
showit:any;
nestedjson:any;
constructor(private formBuilder: FormBuilder,public service: RxSpeechRecognitionService) {
}
ngOnInit() {
}
}
1) To the question in your headline: How to call a component from other component
You can give the header component a reference id inside the home template.
<app-header #header></app-header>
Then you can access the header component through a ViewChild in your home component.
#ViewChild('header') headerComponent: HeaderComponent;
But this does not seem to be very good practice for your needs. Consider using a service and subscribe to a Subject by using RxJs Observables. Or much simpler in your case: just use two-way-data-binding.
2) The way you should actually communicate between components: two way data binding
header.component.ts
export class HeaderComponent implements OnInit {
#Input() isChecked: boolean;
#Output() isCheckedChanged = new EventEmitter<boolean>();
constructor(public router: Router){}
ngOnInit() {
}
}
header.component.html
<input [(ngModel)]="isChecked" type="checkbox">
home.component.ts
export class HomeComponent implements OnInit {
isChecked: boolean;
constructor() {}
ngOnInit() {
}
}
home.component.html
<app-header [(isChecked)]="isChecked"></app-header>
Edit: in your case you also don't need two way binding since you don't need any feedback from the HeaderComponent. One way data binding will be fine. Then you can remove the line
#Output() isCheckedChanged = new EventEmitter<boolean>();
And in Home template don't use banana in the box syntax [()], instead just use []:
<app-header [isChecked]="isChecked"></app-header>
You can make use of a service which is defined at the root level.And then with the help of a service you can either emit or use Subjects to capture in your home component.

Component Interaction #Input

I would like a component to send input to another component. Below is the code .ts and .html. of the two components.
Now the problem is that the html page of the parent component also shows the html part of the child component ... I want the component to pass only one string to the child component
Parent.ts
import ...
#Component({
selector: 'app-parent',
templateUrl: './parent.html',
styleUrls: ['./parent.css']
})
export class ParentComponent implements OnInit {
sostegno : string;
constructor() { }
ngOnInit() { }
avvia1() {
this.sostegno = "xxx";
this.router.navigate(['./xxx'], { relativeTo: this.route });
}
avvia2()
this.sostegno = "yyy";
this.router.navigate(['./yyy'], { relativeTo: this.route });
}
}
Parent.html
<div>
...
</div>
<app-child [sostegno]="sostegno"></app-child>
Child.ts
import ...
#Component({
selector: 'app-child',
templateUrl: './child.html',
styleUrls: ['./child.css']
})
export class ChildComponent implements OnInit {
#Input() sostegno : string;
constructor() { }
ngOnInit() {
console.log(this.sostegno);
}
}
There are some changes which you need to make because looking at the code which your currently have it seems incomplete.
You are using this.router without injecting the Router class in your constructor.
You are using this.route without injecting the ActivatedRoute class in your constructor.
To test that your parent > child interaction is working you can remove your param and instead place a test for the html
<app-child [sostegno]="'Test'"></app-child>
This should work for your ngOnInit function which is inside of your child component. If this works all you need to do now is either initialize sostegno in your parent component else your console log inside your child component will not reflect the changes when you call avvia1 or avvia2 inside of your parent class.
Hope this helps!

Angular 2/4: Can't update child component view

I want to update the value of str which I used in the view of child component from the parent component, by calling the function change() of child component
here is my code.
import { Component } from '#angular/core';
import { ChildComponent } from './child/child.component';
#Component({
selector: 'app-root',
template: `
<h1>parent</h1>
<button (click)="changeChild()">change child</button>
<app-child></app-child>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private cc:ChildComponent) {}
changeChild(){
this.cc.change();
}
}
and the child component is:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-child',
template: `
<p>{{str}}</p>
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
private str;
constructor() {
this.str = 'initial'
}
change(){
this.str = 'changed'
}
ngOnInit() {
}
}
but the value str in the view never updated to "changed".
please Any help because I am new in Angular 4 ??
Use #ViewChild to get reference of child component
in Parent component
import {ChildComponent} from 'child.component.ts'
export class ParentComponent{
------
#ViewChild(ChildComponent)
private child:ChildComponent
---
changeChild(){
this.child.change()
}
}