Inject ordered list with innerHTML in Angular - html

I'm using Angular CLI v13.3.6 with Node v16.12.0 and I've a problem when I use innerHTML property.
I'm using Angular CLI v13.3.6 with Node v16.12.0.
In typescript file I've a variable with an ordered list like this:
let myText = "<ol><li>first</li><li>second</li></ol>";
I need to show this text in a disabled div, so this is the code that I'm using in the html file:
<div id="myId" class="myClass" [innerHTML]="myText" disabled></div>
The result is that the text is shown but the numbers not. The same issue is present when I use the unordered lists. How can I do?

For security reasons, Angular compiler does not accept any string to be injected as HTML. You can bypass this by using DOMSanitizer to "trust" the string and parse it as valid HTML.
You will have to import DomSanitizer and inject it in yopur constructor like:
import { DomSanitizer } from '#angular/platform-browser';
constructor(private readonly domSanitizer: DomSanitizer) { }
And then use DomSanitizer to trust your string to parse it as HTML. You can use like this:
this.domSanitizer.bypassSecurityTrustHtml(YOUR_STRING_HTML);

This has nothing to do with Sanitize html. It is CSS issue.
So to avoid overwritten CSS. You could try:
Creating a brand new angular app: ng new. This way no third party CSS involved
Open the app in Incognito/Anonymous mode, this will help prevent any browser extensions to interfere with your app

Related

Angular: Rendering and Getting the HTML of a Component Dynamically

Render the HTML of a component so that it could be used to open a new tab of the type about:blank (a blank new html page that nothing has to do with the application itself).
Why?
To avoid creating the HTML using a string variable as, for example:
var html = '<div>
<h3>My Template</h3>
' + myProperty + '
</div>';
I saw that you can render a component dynamically using ViewContainerRef.createComponent and ComponentFactoryResolver. The problem with this is that the component is rendered inside the view container, in the application. What I would like to do is generate the HTML of that component so that then I can use that HTML to put it wherever I want. (in this case, in the document property of the object given by the window.open() method)
Example:
#Component({
selector: 'app-component',
template: `
<div>
<h3>My Template</h3>
{{ myProperty }}
</div>
`,
styleUrls: ['./my.component.less']
})
export class MyComponent{
myProperty: string;
}
I expect to use it in this way:
//get new window tab
var newTab = window.open('about:blank', '_blank');
//get the HTML of the component
//use it to open the new tab
newTab.document.write(html);
It may help other people so I post here what I did and which problems I found. After looking to some solutions, this one worked for me. The problem was then I realize that Angular sanitizes your HTML removing all possible <script> tags. Unfortunately I had like 3 of them. In addition, if you don't want them to be sanitized, you have to use a service called DomSanitizerand use the method bypassSecurityTrustScript (doc) passing the script as a parameter. So the idea of don't 'stringify' the code was gone. Saying that, I used the original approach, where the HTML is stored in a variable then passed as a parameter to window.open

Changing fxFlex value in the Component with "setAttribute('fxFlex', '25%')" not Working in Angular 6

I'm using flexLayout module (see more in https://github.com/angular/flex-layout also in https://alligator.io/angular/flex-layout/) to build responsive div in my Angular application and I want to set the value of fxFlex attribute from my Angular Component.
code in the component.ts:
const nav = document.getElementById('nav2'); nav.setAttribute('fxFlex', '5%');
code in the html page:
<div fxLayout>
<div id="nav2" fxFlex="25%" class="col-md-2.5 bg-white p-1">hello</div>
<div id="nav1">word</div></div>
the code should normally should change the size Layout to 5%, but it's not the case, when i inspect the page I found that the attribute has been change but the layout still the same, oddly when i change it manually in the html code to 5%, i get the result that i wanted.
I'm using Angular 6, and Typescript 3.1.1
Please, If there is any suggestion, do not hesitate.
Thank You !
the code should normally should change the size Layout to 5%
No it should not.
Angular directives are ussed in Typescript, or in a pre-build context.
When you write
document.getElementById('nav2'); nav.setAttribute('fxFlex', '5%')
You instruct the Javascript, that has been compiled from Typescript (so in a post-build context) to get the element and add an Angular directive to your attribute.
The thing is, the code is already compiled, so you can't add typescript to Javascript, otherwise you would have to compile it again (and I'm not even sure you can do that).
I suggest you learn about angular features and how it works before using it. Also, consider posting a Minimal, Complete, and Verifiable example if you want someone to offer a solution adapted to your case.
In angular, you need to use the renderer2 to setAttribute dynamically.
Example:
HTML
<div #myDiv id="nav2" fxFlex="25%" class="col-md-2.5 bg-white p-1"></div>
component.ts
import {ElementRef,Renderer2} from '#angular/core';
...
export class MyComponent implements AfterViewInit {
#ViewChild('myDiv') el:ElementRef; // get the refernce of dom element.
constructor(private rd: Renderer2) {}
ngAfterViewInit() {
// Update dom after view initialized.
this.renderer2.setAttribute(this.el.nativeElement, "fxFlex", "5%");
}
}

Accessing HTML field of Parent Component in Library's component

I have created an Angular 6 library using 'ng generate library' command. This library is used in my base component after --prod build and then importing in app.module.ts of main application. The ...Component file in Library has #Input("leftPanel") leftPanel: ElementRef;
HTML Div element on base.component.html is like this: <div #leftPanel></div>
And the library element using its selector :
<lib-ng-mylibrary [leftPanel]="leftPanel"> </lib-ng-mylibrary>
Library component implements AfterViewInit. In the implementation method, this code execution fails: this.leftPanel.nativeElement.style.flexBasis = '50%';
it says, this.leftPanel.nativeElement is undefined. But i can see this.leftPanel point to the div. Wonder why it does not allow this.leftPanel.nativeElement` even tho #Input leftPanel is of type 'ElementRef'?
Thanks in Advance!
Harshad
Instead of sending the parent ElementRef my feeling is that your component should have and #Output and trigger an event handled by the parent, to change the native panel width.
Doing like you reduce the coupling between the object and make them more reusable.
See docs here: https://angular.io/guide/component-interaction
Still want to use ElementRef as parameter
If you still want to send the leftPanel as a parameter, you will need an #Input() variable in your main component as well, so it can resolve <div #leftPanel> to a local variable and that variable be used in [leftPanel]="leftPanel"
cheers

How to add custom CSS defined by some user input in Angular4?

I want to give users of my application the possibility to set plain CSS styles and those style definitions should be applied immediately to some HTML elements.
For example, I have a textarea bound to a model in my component:
<textarea #customCss></<textarea>
In the same component, I defined a HTML element and for that HTML element, I want to give the user the possibility to assign plain CSS and allow the user to immediately preview the styled element. So basically, I would expect something like the following (which isn't working since the style property is readonly):
<div style="{{ customCss.value }}">CUSTOM STYLED DIV</div>
Therefore, when a user enters background:black;color:red; in the textarea, I would expect that the HTML for the styled element would be rendered as:
<div style="background:black;color:red;">CUSTOM STYLED DIV</div>
I don't see any chance to use the ng-style directive here directly since it would expect some JSON code and not plain CSS code.
So how can I tackle this problem in Angular4?
Probably the easiest way is to just bind to the attribute:
<div [attr.style]="customCss.value">CUSTOM STYLED DIV</div>
Niles advice got me back on the right track, thanks for that.
I already tried [attr.style]="..." before but without success but the problem was that the resulting CSS rendered to "unsafe" (at least in Safari), see this Github issue.
Therefore, I wrote my own Pipe using the DomSanitizer in order to get this work. Here is the code:
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Pipe({name: 'safeStyle'})
export class SafeStylePipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) {}
transform(style) {
return this.sanitizer.bypassSecurityTrustStyle(style);
}
}
Our custom pipe can then be used as usual with:
<div [attr.style]="customCss.value|safeStyle">CUSTOM STYLED DIV</div>

Is it possible to use Polymer inside of React?

I have been using React and look to use Polymer tags inside of React. React does not recognize Polymer tags as React only handles basic DOM tags. Is there a way to add the Polymer tags to React DOM library?
Yes, it is possible.
Create a polymer element.
<link rel="import" href="../../bower_components/polymer/polymer.html">
Polymer({
is: 'calender-element',
ready: function(){
this.textContent = "I am a calender";
}
});
Make the polymer component a html tag by importing it in a html page. E.g. import it in the index.html of your react application.
<link rel="import" href="./src/polymer-components/calender-element.html">
Use that element in the jsx file.
'use strict';
import React from 'react';
class MyComponent extends React.Component{
render(){
return (
<calender-element></calender-element>
);
}
}
export default MyComponent;
Is it possible to use Polymer inside of React?
Short answer: not really.
Long answer: kinda. You have to create components which directly create the nodes and manipulate attributes. There are also other considerations for children of the element, etc.
Is it possible to use React inside of Polymer?
It's pretty much the same answer this way, you'd have to wrap a React component in a polymer element.
Why?
Polymer (based on web components), and React (a ui component library), are both based on 'components'. Because there's no single way to express a component in web, you'll need to bridge between the various libraries. The same holds true for questions about 'react in angular', 'jquery plugin in react', 'knockout in jquery plugin', 'react in backbone', 'angular with polymer elements which use backbone and react with polymer elements which use angular', etc.
In a case like angular with polymer, you might think it's very simple, but polymer doesn't know about evaluating angular expressions, or any kind of declarative callbacks. You need a bridge in nearly every case, and they're never pretty.
this is a fairly old question but how about https://www.npmjs.com/package/react-polymer ? isn't this a support of polymer components for react?
import reactPolymer from 'react-polymer'; //IMPORTANT: Must be imported before React.
import React from 'react';
reactPolymer.registerAttribute('raised');
reactPolymer.registerAttribute('url');
reactPolymer.registerEvent('response', 'onResponse');
<paper-button raised>another button</paper-button>
<iron-ajax url="http://example.com/" onResponse={this.handleResponse} />
Answer according to current stages of react and polymer
Since this question was asked a while ago and a lot has changed since then, I'd like to add that you can now use polymer elements in react directly but for your custom attributes and events it causes problem it can easily be handle by using react-polymer, It has support for almost all elements, with exception of gold-* elements.
Why would you want to use Polymer with react?
It can further simplify your development process or make it a big mess. It depends on how you use it
Speed of development and ease of use offered by polymer components is unrivaled.
React can further break down your components comprising of polymer components, into manageable pieces.
Simply because, react and JSX is love.
Hey why the hell not??
The answer is YES. But it is not straight forward. So, I tried following some documentations which are around in fact even the official one but the best was this: https://medium.com/jens-jansson/start-using-web-components-in-react-6ccca2ca21f9
I followed the steps mentioned and it worked! I am also mentioning the github repo wherein I tried to integrate the vaadin datepicker and also one of the polymer element paper-input. https://github.com/manit815/react-with-webcomponent
Yes, you can use Polymer element inside react.
Create Polymer element
import { LitElement, html } from 'lit-element';
export class CustomButton extends LitElement {
static get properties() {
return {
isDisabled : { type: Boolean },
buttonType: { type: String },
};
}
constructor() {
super();
this.isDisabled = false;
this.button = 'button';
}
render() {
return html`
<button>
<slot></slot>
</button>
`;
}
}
customElements.define('polymer-button', CustomButton);
Import the element into an HTML file using <script type="module">.
Use the import statement (as shown above) to import it from another ES6 module.
<script type="module" src="./polymer-button.js">
Once you've imported it, you can use a custom element just like you'd use a standard element.
import React from 'react';
export const PolymerButton = () => {
return (
<polymer-button />
)
}
I just tried this today and I was able to successfully use the material elements from their element catalog. I haven't gotten around to testing it thoroughly, but as far as using the tags in React goes, it works and all the html and css is there.
To use existing elements, just follow their using elements guide.