In Angular i have some template defined as a constant, The template renders fine and all, but I want to attach an event to an element from the html constant. It doesn't seem like i can bind the function as I would normally do when the template is defined in the #Component definition.
Here is a stripped piece of code describing what I have tried.
export class SomeComponent implements OnInit {
public ngOnInit(): void {
const someHtml = `
<a (click)="someFunction()" href="someUrl">link</a>
`
.. some code that uses the const
}
public someFunction() {
console.log("clicked")
}
}
How would I go about this?
Related
I have the following Directive:
#Directive({
selector: '[Foo]'
})
export class Foo implements AfterViewInit {
constructor(private elementRef: ElementRef) { }
ngAfterViewInit(): void {
const element = this.elementRef.nativeElement;
element.title = element.innerHTML;
}
}
If I apply this directive to a div that dynamically fetches data from a field in the component, then set this field to be the string "<" I get "%gt;" instead of "<" in the UI.
I highly suspect this is because I 'get' the pre-rendered text from the HTML element, and it includes a sanitizing mechanism that converts "<" instead of "%gt;".
Assuming I have to use directives and can not specify the title field manually, how can I fix the problem without making inelegant "find and replace"es for all the special characters that are escaped?
Try this,
I think you have to use something called DomSanitizer https://angular.io/api/platform-browser/DomSanitizer,
Also refer to, https://angular.io/guide/security#trusting-safe-values
#Directive({
selector: '[Foo]'
})
export class Foo implements AfterViewInit {
constructor(
private elementRef: ElementRef,
private sanitizer: DomSanitizer
) { }
ngAfterViewInit(): void {
const element = this.elementRef.nativeElement;
element.title = this.sanitizer.bypassSecurityTrustHtml(element.innerHTML);
}
}
I have 3 components in this situation:
-OuterComponent
--MiddleComponent
---InnerComponent
I need to pass a function from OuterComponent to InnerComponent through MiddleComponent.
It is important to mention that the function I need to pass does take an input: DoSomething(node)
I don't know if it is relevant but I am already passing a NodeTree from the OuterComponent to the MiddleComponent and then I am unpacking the NodeTree into a Node and passing it InnerComponent. This Node is what I need to use as an input for the function being passed.
So, I need to be able to use an #Input as the input for the function being passed to the InnerCompoenent, which I assume will need to be an #output.
Method 1:
You can call the parent component function(OuterComponent) from the child component(InnerComponent) using #Output.
OuterComponent HTML:
<MiddleComponent (updateOuterComponent)="parentFunction($event)" />
OuterComponent TS:
export class OuterComponent implements OnInit {
constructor() {}
ngOnInit() {}
parentFunction(para) {
console.log(para);
// operations you want to do in parent component
}
}
MiddleWare HTML:
<InnerComponent (updateMiddleComponent)="middleFunction($event)" />
MiddleComponent TS:
export class MiddleComponent implements OnInit {
#Output() updateOuterComponent = new EventEmitter();
constructor() {}
ngOnInit() {}
middleFunction(para) {
this.updateOuterComponent.emit(para);
}
}
InnerComponent HTML:
It can be whatever you want to write
InnerComponent TS:
export class InnerComponent implements OnInit {
#Output() updateMiddleComponent = new EventEmitter();
constructor() {}
ngOnInit() {}
updateMiddleAndParent(para) {
this.updateMiddleComponent.emit(para);
}
}
Once you call updateMiddleAndParent function form Inner component using emitter, that will trigger middleFunction in the MiddleComponent. After triggering middleFunction, Similarly middleFunction will trigger parentFunction with the help of emitter.
Method 2:
You need to create a service and use it to call the parent function:
DataService:
import {BehaviorSubject} from "rxjs/BehaviorSubject"
export class DataService {
private state$ = new BehaviorSubject<any>('initialState');
changeState(myChange) {
this.state$.next(myChange);
}
getState() {
return this.state$.asObservable();
}
}
call DataService in both InnerComponent and OuterComponent:
In the OuterComponent call DataService and call getState(), this will return an observable whenever the value changes you can any function using data passed in observable response.
In the InnerComponent call DataService and use the changeState() to change the value.
once the value is changed in DataService, then in parent Component the value will be change as you are subscribed to the observable, You will get the updated data from there you can call any function in parent.
I have a model class with a property that returns a value by calling a method, but when i try to bind that property, there is result on the page, but also no error occuring.
export class TestClass {
testProperty: string = this.getString();
getString() {
return 'hello';
}
}
in html:
{{model.testProperty}}
Does Typescript / Angular not support this? What is the common way to do it?
This is a simple enough class. What you could do is initialize testProperty as null or by a default value and in ngOnInit() assign the returned value from the function.
import { Component, OnInit } from '#angular/core';
export class TestClass implements OnInit {
testProperty: string = null;
ngOnInut() {
this.testProperty = this.getString();
}
getString() {
return 'hello';
}
}
The ngOnInit() is a lifecycle hooks and runs when the component is initialized.
public get testProperty(): string {
return 'hello'
}
If you use the 'get' after the public, it allow the function to be called as it would be a normal variable. I think you shouldnt even need the 'model.'
I want to call a static class method/function from out of my HTML in Angular 7. This function is not in the component.ts but in a separate general class file message.ts.
An error is displayed on the console :
TypeError: Cannot read property 'msg1' of undefined.
Template:
<div>
{{ Message.msg1({ 'x': 'abc', 'y': 'def' }) }}
</div>
message.ts:
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class Message {
constructor() { }
public static msg1 (items: []): string {
// some code
}
}
Is what I want possible ? If yes, how can I get the message file (and so the Message class) in scope of the HTML?
Static methods are accessible on the class, not the instance injected by DI. If you want that template code to work, you'd have to do e.g.
import { Message } from ".../message";
#Component(...)
class Whatever {
Message = Message;
...
}
to make the class available as Message in the template scope.
That said, it's unclear why that method is static, or what the point of an injectable service with only a static method is.
In the document class, I got the following code:
package {
...
public class Main extends Sprite {
public function Main(){
...
model:IModel = new Model();
controller:IController = new Controller(model);
var controls:CompositeView = new Controls(model,controller)
//Accessing controls.x provokes 1202: Access of undefined property x in package view
}
}
}
Where class CompositeView is a extension of Component which in turn extends Sprite.
Component:
package view
{
....
public class Component extends Sprite
{
...
}
}
CompositeView:
package view
{
....
public class CompositeView extends Component
{
...
}
}
Controls:
package view
{
....
public class Controls extends CompositeView
{
...
}
}
But unfortunately, when I try to access controls.x I get a undefined property error.
Changing the package for all classes to the same name fixed this issue. E.g use package for everything instead of package and package.view.
What can be done in Actionscript to keep code organization and avoid this issue ?
Problem solved: var controls was used as a package name, changing name of the variable solved.