shady-render.ts:46 Uncaught TypeError: result.getTemplateElement is not a function - polymer-3.x

When I try executing Polymer element locally,I am using polymer 3 and my HTML structure is HTML5.
The counter-comp tag is added in my html file.
import {LitElement} from "#polymer/lit-element/lit-element.js"
class CounterComp extends LitElement{
constructor(){
super()
}
static get properties(){
return{
color:String,
background :String,
fontweight: String
}
}
_render({color,background,fontweight}){
return html`
<style>
.title{
background:$(background) ;
color: $(color);
font-weight:$(fontweight) ;
padding: 15px 25px;
}
</style>
<div class = "title">"This is in div tag with class title"</div>
`;
}
}
customElements.define("counter-comp",CounterComp);
<counter-comp color="green" background="blue" font-weight="355">
</counter-comp>
shady-render.ts:46 Uncaught TypeError: result.getTemplateElement is
not a function at result (shady-render.ts:46) at render
(shady-render.ts:130) at HTMLElement._applyRender
(lit-element.ts:232) at HTMLElement._propertiesChanged
(lit-element.ts:183) at HTMLElement._flushProperties
(properties-changed.js?module:335) at HTMLElement._flushProperties
(lit-element.ts:194) at HTMLElement.ready
(properties-changed.js?module:179) at HTMLElement.ready
(lit-element.ts:107) at HTMLElement._enableProperties
(properties-changed.js?module:315) at HTMLElement.connectedCallback
(properties-mixin.js?module:200)
I am getting the above Error please check and help to get this solved.
Thanks

Instead of:
import {LitElement} from "#polymer/lit-element/lit-element.js"
use:
import {LitElement, html} from "#polymer/lit-element/lit-element.js"

Related

How to set up styleClass inside ts file?

I want to create css element inside ts file and pass it as a styleClass to PrimeNg Toast.
var style = document.createElement('style');
style.innerHTML = '::ng-deep .cssClass { background-color: #e62323; border: solid #8A427A; border-width: 0 0 0 6px; color: #2c1e30; }';
this.messageService.add({severity:'custom', summary:'Service Message', detail:'Via MessageService', styleClass: 'cssClass', sticky: true});
The above code is not working for me, style is not applied.
Could someone help me with that?
EDIT: I tried to catch the p-toast and append style but it's not applied still.
setTimeout(() => {
let message = document.getElementsByClassName('p-toast-message-custom')[0];
message.appendChild(style);
}, 100)
In Angular we should not set a style with directly DOM manipulation. The reason is:
Angular cannot detect changes if you do this by hand
Angular render components and create and update the DOM.
So its possible, but not a good way. In your case, set append the element to the DOM. Then it will works, I think.
The Angular Way
Each component has it one contained CSS/SCSS.
What you can do is to use Angulars board means, like ngStyle, ngClass and so on. example:
<div [ngStyle]="{'background-color':'green'}"></<div>
You can do it with property binding, too:
// Code
getColor(country) { (2)
switch (country) {
case 'UK':
return 'green';
case 'USA':
return 'blue';
case 'HK':
return 'red';
}
}
// Html
<div [ngStyle]="{'color':getColor(person.country)}">Test</div>
ngClass does the same but let you set a class flexible to any component.
// Code
val: number = 9;
// Html
<td [ngClass]="val > 10 ? 'red' : 'green'">{{ val }}</td>
Link to ngClass docu, link to ngStyle docu.
To add a class to a message using PrimeNG's MessageService, you can use the add method and provide an optional options object that includes a styleClass property.
Here's an example code snippet that demonstrates how to add a class to a message:
import { Component } from '#angular/core';
import { MessageService } from 'primeng/api';
#Component({
selector: 'app-my-component',
template: `
<button (click)="showSuccess()">Show Success Message</button>
`,
providers: [MessageService]
})
export class MyComponent {
constructor(private messageService: MessageService) {}
showSuccess() {
this.messageService.add({severity:'success', summary:'Success', detail:'Message Content',
options: {styleClass: 'my-custom-class'}});
}
}
.my-custom-class {
background-color: #b3ffb3;
color: #006600;
border: 1px solid #006600;
border-radius: 5px;
padding: 10px;
}

ReactJS: Extend, Override CSS class

I want to
import a style class from a CSS file
dynamically extend or override the style
Apply the new style to react component.
Pseudocode of what I want to achieve
import 'common.css'
function MyComponent() {
if (somethingHappened) {
style = extendOverrideStyle(styleClassFromCSS)
} else {
style = styleClassFromCSS
}
return (
<SomeComponent className=style />
)
}
How can I do this?
Update:
Check my answer in the replies for how I finally did this.
Just create a new class in your CSS file to override the old CSS.
Then do it as
function MyComponent() {
return (
<div className={somethingHappened ? 'firstclass overwriteclass' :
'firstclass'}>
<SomeComponent />
</div>
)
}
You can't set style in Component Directly.
First you need to pass the style as prop to your Component and set style inside that component
<SomeComponent prop_class={your_style}/>
Inside SomeComponent
<div className={this.props.your_style}>
</div>
Answer (implementation somewhat similar to #Rohan's answer):
The main css class is the base style rules and .main.somethingHappened extends/overrides it. The main css class is applied to myComponent initially. When somethingHappened is true, apply both css classes main somethingHappened to myComponent.
mystyle.css
.main {
...
margin: 10px;
}
.main.somethingHappened {
margin: 5px
padding: 5px;
}
myComponent.js
(uses classnames library. check #Rohan's approach to avoid classnames library.)
import 'common.css'
import classnames from 'classnames'
function MyComponent() {
let didItHappen = ...
return (
<SomeComponent
className={classnames('main', {'somethingHappened': didItHappen})}
/>
)
}

How to limit style to component level in React?

My app tries to show emails. Sometimes the style in the email will affect the app itself.
Right now I am using the package juice to inline style in the email html. However, sometimes it cannot inline correctly. So I try to find other solutions.
I know Angular automatically add some random string in each class to make sure style in one component won't affect other component, is there a same way to do it in React? Or is there other way to limit style to the component level without using iframe? Thanks
The demo shows the p { color: red; } from the email also affects the app itself. In this case, it affects Content in app.
Live demo
class Mail extends Component {
render() {
// the style inside is from mail, in real case, it can have tens or even hundreds of different styles
const mailFromServer = `
<html>
<head>
<style>
p { color: red; }
</style>
</head>
<body>
<p>Content in mail</p>
</body>
</html>
`;
return (
<div>
<div dangerouslySetInnerHTML={{__html: mailFromServer}} />
</div>
);
}
}
class App extends Component {
render() {
return (
<div>
<Mail />
<p>Content in app</p>
</div>
);
}
}
There are few ways to do this.One of the way would be by passing style to the elements and defining styles as objects. For example
const styles = {
content: {
color: '#000',
backgroundColor: '#fafafa',
},
};
class Mail extends React.Component {
render() {
return() {
<p style={{styles.content}}> Content </p>
}
}
}
If you really want something scalable then you can use styled-components which for me personally work really nicely and fulfills all your styling needs.
You'll need to use a class to limit the style to a specific component's features:
import React, { Component } from 'react';
import { render } from 'react-dom';
class Mail extends Component {
render() {
const mail = `
<html>
<head>
<style>
.mail-header { color: red; }
</style>
</head>
<body>
<h1 class="mail-header">Heading in mail</h1>
</body>
</html>
`;
return (
<div>
<div dangerouslySetInnerHTML={{__html: mail}} />
</div>
);
}
}
export default Mail;
Styles in <style>..</style> or from CSS sheet is global. They are applied across your app.
If you have control over how the email is formatted, I would recommend setting different class names for different email types.
If you have a limited set of email types, you can specify the styles for each of them in a css sheet, and import it on your html file or Webpack.
styles.css
.important-email { color: red; }
.not-important-email { color: blue; }
// ...
// styles for different email types
Mail.jsx
class Mail extends Component {
render() {
const mail = `
<html>
<head>
</head>
<body>
<h1 class="important-email">Heading in mail</h1>
</body>
</html>
`;
return (
<div>
<div dangerouslySetInnerHTML={{__html: mail}} />
</div>
);
}
}
export default Mail;
Yes, you can use CSS Modules, which is one or more css files (written in js) in which all class names are auto-scoped locally to each component by default.
There is a good article about this here https://medium.com/#pioul/modular-css-with-react-61638ae9ea3e
You can also try to reset those known html entities which are commonly over-ridden by your Mail html. You may have to play around a bit, but, given your example, you could do something like the following:
https://stackblitz.com/edit/react-neymbb
Basically, in my sandbox I reset your paragraph color and padding to their defaults, as well as, used it in conjunction with another inline style. Depending on the entire construct of css inheritance in your app, your results may vary, but you should be able to get something workable.
More information on the css values I recommend found here:
https://developer.mozilla.org/en-US/docs/Web/CSS/initial

Angular2 CSS style/class strings as inputs to component

Background
I have a component that wraps two span elements. I would like parent components to be able to style the inner two spans by specifying CSS classes and styles as inputs (preferably as simple strings). Here's a simplified example of what I would like this to look like:
Code
app component (parent)
#Component({
selector: 'my-app',
template: `
<div>
<app-two-spans [classArg1]="'class1'" [classArg2]="'class2'"
[styleArg1]="'width: 100px'" [styleArg2]="'width:200px'"></app-two-spans>
</div>
`, style: `
::ng-deep .class1 {
border: 1px solid black;
}
::ng-deep .class2 {
border: 1px solid blue;
}
`
})
export class App {
}
two spans component (child)
import {Component, Input, Output, EventEmitter} from '#angular/core';
#Component({
selector: 'app-two-spans',
template: `
<span *ngIf="flag" [ngClass]="classArg1" [ngStyle]="styleArg1"
(click)="flag = !flag">click me</span>
<span *ngIf="!flag" [ngClass]="classArg2" [ngStyle]="styleArg2"
(blur)="flag = !flag" contenteditable="true">
click me to change my value</span>
`
})
export class TwoSpansComponent {
flag: boolean = true;
#Input() styleArg1: string;
#Input() styleArg2: string;
#Input() classArg1: string;
#Input() classArg2: string;
constructor() {}
}
Problem
The class styling seems to work in my local environment (though it doesn't seem to work on Plunker for some reason). However, the styles are not showing up. I've seen other posts about styles as inputs, but from what I've seen this is usually done by passing style-value pairs (see accepted answer here). However, I would really like to pass these styles as a simple string to make working with the component easier.
I notice the following error in the console: ERROR Error: Cannot find a differ supporting object 'width: 100px'. I'm not sure what this means at all.
Plunker here
Is there a way to do this? How can I give parent components the ability to stylize children?
ngStyle accepts an Object instead of plain string. You can pass your styles as:
[styleArg1]="{ width: '100px' }"
[styleArg2]="{ width: '200px' }"

CSS Modules, React and Overriding CSS Classes

I am using a React component library (React Toolbox), which is outputting this class in their Tab component using CSS Modules and Webpack: label___1nGy active___1Jur tab___Le7N The tab is a className prop I am passing down. The label and active classes are coming from the library. I want to apply a different set of styles on active, something like .tab.active where tab is referring to the styles I have created and active matches the generated selector the library has created but cannot figure out how to do this with css-modules. I need to override this dynamically selector: .label___1nGy.active___1Jur.
[]]2
[]3
Old post but still relevant, so adding an answer to help those with similar issue
While not inherently possible in CSS modules alone, the author of the react-toolbox library has actually solved this particular problem very nicely
Read their github docs which are more in depth on the subject at https://github.com/react-toolbox/react-toolbox#customizing-components
A list of the themeable classes for a particular component is given on the component demo page on their site too
In your case as well as passing a className for tab, you would also create a theme with classes that overrides that desired parts of the default theme and pass that as the theme prop. For example something alog the lines of...
MyComponentWithTabs.css
.tab {
color: white;
}
MyTabTheme.css
.active {
color: hotpink;
}
MyComponentWithTabs.js
import styles from './MyComponentWithTabs.css'
import tabTheme from './MyTabTheme.css'
// blah blah...
return <Tab key={index} className={styles.tab} theme={tabTheme} />
Under the surface this uses a decorator they have abstracted into separate library react-css-themr, I recommend giving that a read too as it explains how the defaults are composed with your overrides in much greater depth, including the different merging strategies they use
I had a similar case, and I solved it like so:
import classNames from 'classnames';
...
const activeClassName = {};
activeClassName[`${styles.active}`] = this.props.isActive;
const elementClassNames = classNames(styles.element, activeClassName);
return <div className={elementClassNames} />
I'm using the classnames package to dynamically add the active class based off of the isActive prop. Instead of an isActive prop you can provide any boolean value.
A more terse way of doing this may be:
const elementClassNames = classNames(styles.element, {[styles.active]: this.props.isActive});
CSS modules won't allow you to safely override the active className (largely by design). Really it should be exposed via an API, e.g. 'activeClassName'.
If the maintainers disagree or you need this quick then you can quite easily add your own active className because your implementing component is managing the index state:
import {Tab, Tabs} from 'react-toolbox';
import styles from './MyTabs.css';
class MyTabs extends React.Component {
state = {
index: 1
};
handleTabChange(index) {
this.setState({ index });
}
render() {
const { index } = this.state;
return (
<Tabs index={index} onChange={this.handleTabChange}>
<Tab label="Tab0" className={index === 0 ? styles.active : null}>
Tab 0 content
</Tab>
<Tab label="Tab1" className={index === 1 ? styles.active : null}>
Tab 1 content
</Tab>
</Tabs>
);
}
}
Disclaimer: Code is untested.
Group style loader
You can use the group-style-lader to override the style of the components. This loader gives you an easy and intuitive way of override the style of the components.
Configure the loader
Install the loader
npm install --save-dev group-style-loader
Configure the loader in your webpack settings
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'group-style-loader',
'style-loader',
{
loader: "css-loader",
options: {
modules: true
}
}
]
}
]
}
};
You only need to put it, before the style-loader or the mini-css-extract-plugin loader.
Override the style of the components
The next example show as you can to override the style of the Card component from the App component.
You can define the style of your component as you are used to.
card.css
.container {
width: 300px;
height: 400px;
border-radius: 8px;
}
.title {
font-weight: bold;
font-size: 24px;
}
.summary {
margin-top: 24px;
font-size: 20px;
}
The unique difference is that in the Card component, you going to use the mergeStyle function to merge the custom style with the default style of the component.
card.jsx
import React from 'react';
import { mergeStyle } from './card.css';
export function Card({ customStyle }) {
const style = mergeStyle(customStyle);
return (
<div className={style.container}>
<div className={style.title}>Title</div>
<div className={style.summary}>
Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor.
</div>
</div>
)
}
Then, in the App component, to override the style of the Card component you need to define the custom style of the Card component using the separator _. All the classes using this separator going to be grouped in the card property of the style object.
app.jsx
.title {
font-size: 32px;
font-weight: bold;
margin: 44px;
}
.list {
display: flex;
}
.card_title {
color: blue;
}
.card_summary {
color: green;
}
Finally, you only need to pass the custom style of the Card component through the customStyle property of it.
app.jsx
import React from 'react';
import { Card } from './card';
import { style } from './app.css';
export function App() {
return (
<div>
<h1 className={style.title}>Group style</h1>
<div className={style.list}>
<Card/>
<Card customStyle={style.card}/>
</div>
</div>
);
}
In the previous example, you have two Cards components, the first uses its default style, and the second uses the customs tyle that we have defined.
You can see a full explanation of how to use the group-style-loader in its repository.
Using :global(.classname) you can override the external classnames.
Even 3rd party library css can be override.
:global(.active) {
color: hotpink;
}
trick in fileName.css
add className-active after declaring className
.className{
background: white;
}
.className-active{
background: black;
}
<div className={'className className-active'} />
<div className={'className-active className'} />
divs always will be black

Resources