Angular 5 - Bind a component selector with InnerHtml - html

I have a component1 selector that I called "app-component1".
#Component({
selector: 'app-component1',
templateUrl: './test-widget.component.html',
styleUrls: ['./test-widget.component.scss'] })
So to call the html of this component I usually use:
<app-component1></app-component1>
and it works perfectly fine.
Now from another component2 I have the following variable:
variableToBind = "<app-component1></app-component1>";
And In the html of component 2 I used the following:
<div [innerHtml]="varibableToBind"></div>
The html code binding isn't working. Is is possible to help me understand why and maybe help me find another alternative?

Thanks Everyone for the suggestions, I actually just find the answer to this:
This can't work because innerHtml is rendered AFTER Angular's compiled the templates. That means that it doesn't understand your selectors at this point of time.
If you guys want to load a component (or any content) dynamically, you should use *ngIf. It worked perfectly fine for me.

Angular sanitizes the HTML to prevent XSS attacks. You should find something like WARNING: sanitizing HTML stripped some content (see http://g.co/ng/security#xss). in your console output.
For further information, check out the documentation on property binding (esp. content security) and the security docs.
Depending on your use case, you need to choose another approach.

Your example code is not a valid approach as
1) html code cannot be bound to element property directly for security reason. ref: https://angular.io/guide/security#xss
2) There is no need to do property binding for HTML in your case. If you want to perform different logic inside AppComponent2, the best practice is to do property binding for the parameters that can customise component behaviours:
<div>
<app-component1 [prop1]="myVar1" [prop2]="myVar2"></app-component1>
</div>
and then you can customise it from the component properties instead of the component itself. This would make more sense.

If you really* need to pass HTML to component (for example if you have text with <br> tags or something like that), you can create custom Input like so:
export class YourComponent {
#Input() public htmlContent = '';
}
<div [innerHtml]="htmlDescription"></div>
And use it like so:
<your-component [htmlDescription]="textWithHtmlTags"></your-component>
* - for example if a string of text with basic HTML formatting tags (like <b>, <i> or even <br>) needs to be rendered.

In Angular, it is generally not recommended to bind a component selector using the [innerHTML] binding, because this can lead to security vulnerabilities. Instead, you should use Angular's template syntax and component structure to include components in your templates.
If you need to dynamically choose which component to include based on some condition, you can use the ngIf directive and the element to include a component only if a certain condition is met.
<ng-template [ngIf]="showMyComponent">
<my-component></my-component>
</ng-template>

Related

What does it mean to set data-target attribute of a div to the id of that div?

I'm reading some code and there is a piece of html that reads:
<div id="uniqueId1234" data-target=".uniqueId1234">
...
</div>
and then earlier on in the same html file there is a span element that seems to use this div as a class:
<span class="uniqueId1234">
...
</span>
Can someone explain how this works? I thought that a class was something created in a css file. Sorry if this is a dumb question.
This is likely part of some piece of Javascript code or a library that listens for some type of change or event on your element with the data-target attribute.
When this event is triggered, it can then use the value of that attribute as a selector for performing some other logic as seen in this basic jQuery-based example below:
// When an element containing your data-target attribute is clicked
$('[data-target]').click(function(){
// Find the appropriate target (i.e. ".uniqueId1234")
var target = $(this).data('target');
// Then use it as a selector for some type of operation
$(target).toggle();
});
Classes are very common within CSS to style multiple elements, but they can also commonly be used as a mechanism in Javascript as well, which is likely the case in your scenario here.
What does it mean to set data-target attribute of a div to the id of that div?
Nothing standard. data-* attributes are designed to hold custom data for custom code (typically client side JS) to process.
I thought that a class was something created in a css file.
Classes are an HTML feature used to put elements into arbitrary groups. They are commonly used when writing CSS, but also client side JS and other code.

Angular Tags disrupting CSS stylings

I have a project being built with the Angular 2 framework. The custom angular tags (<my-app>, <my-whatever-component> etc.) keep disrupting the css output. When the HTML is directly on the index.html file (not in any component whatsoever) the CSS loads alright.
I have debugged and have come to the certain conclusion that the custom angular tags are the cause of the issue.
What do i do to change this behavior? How can i make the custom Html tags vanish after the view is rendered ? This will prevent Hierarchical CSS rules from breaking.
Edit 1 : I forgot to mention the CSS is custom (Free bootstrap admin template thingy) so i can't (more like i don't want to) tweak it.
You need to set View Encapsulation Types, More information here
#Component({
moduleId: module.id,
selector: 'my-zippy',
templateUrl: 'my-zippy.component.html',
styles: [`
.zippy {
background: green;
}
`],
encapsulation: ViewEncapsulation.None //No Shadow DOM at all. Therefore, also no style encapsulation.
})
EDIT
As a workaround you can use an attribute selector in your component like
selector: '[my-component]'
and then use it like
<div my-component>Hello My component</div>
This way you can skip component tags from your HTML and can apply hierarchical css.
Can you give an example through pluncker or similar?
Are you using the twitter bootstrap bootstrap.js or the UI Bootstrap?
If you are just using the straight up twitter bootstrap you will have problems using any of the bootstrap components that are implemented in javascript.
Hope that helps

What is the polymer "is" property?

I am new to polymer and keep seeing the "is" property, but never get a thorough explanation of it. Example :
<script>
Polymer({is: "some-property"})
</script>
or
<template is="dom-repeat"></template>
It seems to be a declaration of inheritance or the like and i sorta get it but would like to find a clear explanation.
Per the documentation:
To register a custom element, use the Polymer function, and pass in
the prototype for the new element. The prototype must have an is
property that specifies the HTML tag name for your custom element.
In this case, the
<template is="dom-repeat"></template>
is a specific custom element built-in to Polymer.js, which extends the native HTML template element.

Should Angular Elements Be Treated As Blocks or Wrappers

When using element directives I have seen Angular element directives used in two ways:
1. As block level components
The element is styled as display:block, is the component and its children are the component's children, so the element itself is the component.
Use of directive:
<example class="Example"></example>
The directive's html:
<header class="Example-header"></header>
<img class="Example-image">
<footer class="Example-footer"></footer>
2. As an inline wrapper of the component
The element is left as display:inline and effectively acts as an invisible wrapper for the component itself:
Use of directive:
<example></example>
The directive's html:
<div class="Example">
<header class="Example-header"></header>
<img class="Example-image">
<footer class="Example-footer"></footer>
</div>
Obviously each have advantages and disadvantages for example extra markup, loss of layout context due to inline element etc, but is one the correct way? or is this another of Angular's vagaries?
I'm surprised no one responded, but the idea behind creating custom directives is the ability to create reusable pieces of code that fulfill a specific bit of functionality on your site.
This functionality, however, doesn't care about the styles that you are going to use. You can of course conditionally change classes and styles from within Angular, but the core component when dealing with the framework is the data.
With that being said, there is no "correct way" as you bolded in your question. Develop the directive to fit your needs and style of your site.
First this is probably opinion based but i'd really like to share my point of view about this.
If you really follow angular way of doing directives none of theses are a correct way.
Directives are intended to add a behavior to an HTML element.
The less the directive add HTML the best it is as it allow you to have a better control on this element.
Lets take an exemple.
We have a data grid (let say ui-grid, it doesn't really matter)
<ui-grid ...>
...
</ui-grid>
I had a the idea to add some button to add or remove element in the grid.
I first came up with this
<ui-grid ...>
...
</ui-grid>
<button ng-click="addItem()">Add</button>
<button ng-click="removeItem()">Remove</button>
I'm really happy with this and that's ok, but finally i need to use theses buttons in some other views. I'll have to duplicate the HTML, duplicate the JS and adapt it to the collection.
The common mistake
That's obviously not a good idea.
Instead i will do a directive. Lets say "button-list" : it produce the same html and behavior.
<ui-grid ...>
...
</ui-grid>
<button-list></button-list>
That's pretty cool.
Now i have some need. On one view i need the add button to be blue, on an other one i don't need to have a remove button, and on a last one i want the button text to be "X" and "+" (That's was some request by a client in a true story).
I could make a big object with a list of option and etc... but this is really painful and you need to touch the directive each time you need to add a custom different little behavior.
The good way to go
Now lets just think again about what i wanted to do.
I want the button to interact with the grid... and that's pretty much all. This is how we should go building a custom directive.
We could then produce this directive this way :
<div grid-button-container collection="mycollection">
<ui-grid ...>
...
</ui-grid>
<button grid-add-item>Add</button>
<button grid-remove-item>Remove</button>
</div>
So what do we have here ? We have three different directives.
grid-button-container : Its responsibility is to hold the list for the sub-directives.
grid-add-item : It add a function on click that add an element to the collection of grid-button-container.
grid-remove-item : It add a function on click that remove an element to the collection of grid-button-container.
Both grid-add-item and grid-remove-item will be requiring the grid-button-container to be used.
I cannot describe all the implementation of this (it would take too long) but i think this is how directives should be used. Such as almost no angular build-in directives (ng-*) add HTML and just add a behavior i think all the directives should be build in this way.
Pro :
You have a full control about your HTML
Directives are tiny and trivial
This is really re-usable
Cons :
Can be harder and longer to implement.
To make a final point, the two way you're asking about are just different. No one is better than the other it will just depend on your own HTML organisation and it will depend on the directive use.
Hope it helped.

Is there a way to safely hide HTML tags in AngularJS?

I'm recently starting to explore AngularJS, and of course, i know it is ran at the client side, and since SPA (Single Page Applications) are becoming more and more common, i have a question regarding how to safely hide HTML elements.
Let me give a simple example:
Employee
<div ng-show="canSeeSalary">
{{salary}}
</div>
Now, of course, at runtime the div tag related to the salary won't be displayed, however by seeing the HTML source code, or using a developer tool like the one we have in Chrome, it would be possible to see the tag and probably its value.
I know tags like these should be filtered at the the server-side, of course, but since it has come to the client side, the div will be there.
My question is exactly, if there is any way i could hide these divs from the HTML source code, without needing to mix AngularJS with JSTL, for example.
Thanks in advance.
Try ng-if directive:
<div ng-if="canSeeSalary">
{{salary}}
</div>
Corresponding div element will be removed from the DOM. From the official documentation:
The ngIf directive removes or recreates a portion of the DOM tree
based on an {expression}. If the expression assigned to ngIf evaluates
to a false value then the element is removed from the DOM, otherwise a
clone of the element is reinserted into the DOM.
Use
Employee
<div ng-if="canSeeSalary">
{{salary}}
</div>
ng-if completely removes and recreates the element in the DOM rather than changing its visibility via the display css property
I would recommend using ngCloak rather than ngIf.
The ngCloak directive is used to prevent the Angular html template from being briefly displayed by the browser in its raw (uncompiled) form while your application is loading. Use this directive to avoid the undesirable flicker effect caused by the html template display.
example:
<div ng-cloak> {{::test}} </div>
ngCloak # Official Angular Docs