I am trying to create dynamic print template in Angular 12. I would like to fill the html body text dynamically based on the parameter passed on the selector used in the main component view. Print layout component is in Shared module and both the html templates are in app folder.
My requirements are:
I want to read the html file in the print layout component and
display it. I don't want to create component and render the
component in the print layout
I don't want to save the html file in the backend and trigger api to
fetch the html
print-layout.component.html
<div [innerHtml]="myTemplate"></div>
print-layout.component.ts
#Component({
selector: 'app-print-layout',
templateUrl: './print-layout.component.html',
styleUrls: ['./print-layout.component.scss']
})
export class PrintLayoutComponent implements OnInit{
#Input() modalID;
myTemplate;
ngOnInit() {
if(modalID == "1")
template = '../../app/tools/test/test-message1.html';
else (modalID == "2")
template = '../../app/tools/test/test-message2.html';
}
}
Also, I have gone through this solution Read HTML File into template in Angular 2? where they are creating component dynamically from main component file.
Is there any way to display html template file in the main component without creating component. Also, please suggest is it the right way to display html content without creating component in Angular...?
You can try to use iframe tag inside the print-layout.component.html like this
<iframe [src]="myTemplate"></iframe>
Obviously on ngOnInit() you need to assign path to myTemplate as same name to use in html
Related
In React, you can pass entire components into other components, and then easily display those components in the respective div. This referring not to imports, but rather function parameters so what is displayed will vary.
In Angular, you use #Input() and #Output() to do the same thing with values and functions, but what about components? How do you do this with components? I'm not talking about imports handled by the module file or at the top of the file; I'm talking about parameters that will vary based on the runtime of your program.
I.e, I want to convert the following React code into Angular, where children is another React component passed in via ReactNode:
const ReactComponent = (props) => {
return (
<div>
{props.children}
</div>
);
};
Also I apologize if any of my terminology is incorrect; I'm new to Angular and I'm coming from a (limited) React background.
I tried using #Input() with a parameter of type "any" but this doesn't seem right.
Dynamically, like React, you can use ng-content. This is the opposite of Reacts { props.children }
Use it so (Component - Code Behind)
#Component({
selector: 'btn',
template: `
<button class='btn' (click)="do()">
<ng-content></ng-content>
</button>
`
})
export class ButtonComponent{
do(){
console.log("Ok")
}
}
And the HTML
<div>
<btn>
This is a dynamic Button
</btn>
</div>
This is a dynamic Button can be a component, too. So like this:
<div>
<btn>
<div><span>Hello! </span><button>I'm a button inside a button!?</button></div>
<app-my-custom-component [data]="bindAnything"></app-my-custom-component>
</btn>
</div>
The Result can be look like this:
And here you can play with this on Stackblitz.
Read all about it in the official documentation here.
Content projection
This topic describes how to use content projection to create flexible, reusable components.
To view or download the example code used in this topic, see the live example / download example.
Content projection is a pattern in which you insert, or project, the content you want to use inside another component. For example, you could have a Card component that accepts content provided by another component.
parent.component.html
<div>
<child-component></child-component>
</div>
child.component.ts
#Component({ selector: 'child-component' })
export class ChildComponent {}
This is a very quick way to show how Angular components can be nested. In this example you have a parent component template file (parent.component.html) and inside this file you can include any other component by their selector. In the example I include 'child-component' and show child component ts file.
If you want to make child component dynamic (if I understand you correctly - to pass data from parent to child) and for example pass string value into it, you can:
parent.component.html
<div>
<child-component name="Andrei"></child-component>
</div>
child.component.ts
#Component({ selector: 'child-component' })
export class ChildComponent {
#Input() name: String;
}
More on Angular components communication: https://angular.io/guide/component-interaction
Right now I am creating a library (my-custom-library) and a project in which we'll use that library (called my-Project)
The requirement is, that within my-project I have to use my-custom-library, extended with templates, like this (my-project's app.component.html):
<my-custom-library>
<ng-template #myTemplate>
<div>Some static content for now</div>
</ng-template>
</my-custom-library>
The reason for this is, that in my-custom-library they want to have template-able components, where the template is given from the outside (in this case from my-project).
Within my-custom-library I'm supposed to access the given template(s) and pass them to the corresponding components. This I'm trying to achieve (my-custom-project's app.component.ts)
#ContentChild("myTemplate") myTemplateRef?: TemplateRef<any>;
(my-custom-project's app.component.html)
<ng-container [ngTemplateOutlet]="myTemplateRef"></ng-container>
My problem is, that the contentChild is always empty, the template never renders. The structure itself I think is working, since when I'm moving this same structure within just one project and use it there everything works fine, the contentChild gets its value and "my template" is rendered.
One more information, I don't know if its useful but my-custom-library is created like this (my-custom-library's app.module.ts):
export class AppModule {
constructor(private injector: Injector) {
const customElement = createCustomElement(AppComponent, { injector: this.injector });
customElements.define('my-custom-library', customElement);
}
}
What could cause this issue? Is it even possible to achieve this?
I had the same issue, Apparently ngTemplateOutlet does not work with angular elements. but you can try content projection without ngTemplateOutlet and it works fine.
e.g
<my-custom-library>
<div placeholder1></div>
</my-custom-library>
and you can define placeholder1 within your angular element (my-custom-library)
e.g
<div>
/*your angular my-custom-library code here */
/* the content you want to inject from outside of your angular elements*/
<ng-content select="[placeholder1]"></ng-content>
</div>
Note: you can also do nesting of your angular elements as well using this, but with this approach you have to make sure that ng-content is not affect by any ngif condition, because your angular element can project the content from outside but it can not regenerate projection based on your conditions. those conditions should be added from where you are projecting content.
So I have two components (Preview component and an app component) in an angular project. I displayed one of the components (preview Component) inside the other(app component) through a relative path in an iframe:
app.component.html
<iframe
src="/pagepreview"
width="478"
height="926"
id="iframeId"
#previewFrame
>Alternative text
</iframe>
Now, In the app.component.ts file, I want to access the elements of the preview template, so I did this:
#ViewChild(`previewFrame`,{ static: true }) previewFrame: ElementRef;
onLoad() {
let frameEl: HTMLIFrameElement = this.previewFrame.nativeElement;
let showTemplate = frameEl.innerHTML
console.log(showTemplate )
}
The result I got was the Alternative text word inside the iframe tag.
Does anyone have an idea how I can get to access the HTML tags in the preview component page? I need to do this so I can do some DOM manipulation of the page preview component on the app component page. Thanks.
Apparently the page renders faster than the function that calls the DOM object, despite calling it inside an ngAfterViewInit life cycle hook. I added a setTimeout() function and now I'm able to get the DOM elements I want.
This answer provided the context to my solution.
I'm currently trying to display a svg icon by using Angular component like this
import {Component} from '#angular/core';
#Component({
selector: 'app-profile-icon',
templateUrl: './profile-icon.svg',
styleUrls: ['./profile-icon.component.scss'],
})
export class ProfleIconComponent {
}
An I call this element in a html file. This component is instantiated but with no svg content. Just the path of the svg with some random text.
Is some Angular configuration I missed? Because it works fine if I wrote like this without the component, or just copy paste the svg content to a html template.
<img src='./profile-icon.svg'>
Thanks you very much.
Add assets folder to your angular.json.
"assets": [
"src/assets"
],
Then access the SVG icon in the HTML template like below -
<img src="/assets/profile-icon.svg">
This question is very old, but if somebody else falls here, I've got the same problem trying to show a big SVG file, just got the name of the SVG file in text.
Not sure, but probably because I'm using an old version (Angular 6).
Solved by renaming the svg file as html and changing the templateUrlto point the renamed html file.
I have two components. The first component is a table component --> selector: 'table-component'. This component implements a standard filtering on my table.
My second component is a component for a page that displays the table.
I have multiple pages that use this table component by using the tag.
But some pages need some custom filtering. So how can I add custom filtering in the table component like this?
<table-component>
<custom-filtering>
<div>
Here has to come the filtering stuff
</div>
</custom-filtering>
</table-component>
In your customFiltering directive you must add this
return {
transclude: true,
/* your code */
...
...
}
and then you need to add this to your template
<ng-transclude></ng-transclude>
This mean when you write custom html between tags
<custom-filtering>
// html code here
</custom-filtering>
html code between tags will replaced where your
<ng-transclude></ng-transclude>
in your template..
Is that what you are looking for? Hope this help you
Other way to archive what you want is to extend your customFiltering directive and pass custom filter