How to display `super.styles` and check the inherited properties
GHNewbiee opened this issue · 9 comments
Description
-
Who wants the functionality
I do, GPT GHNewbiee -
What it is they want
I want to display:- the inherited styles i.e.
super.styles
- the inherited properties (see issue)
- the inherited styles i.e.
-
Why they want it
To check that entering is successful and parsing does not fail. Whatever data (properties and styles) are entered by the user, they should be possible to get back for checking. -
Functional description of task/subtask
firstElement.js
import { LitElement, customElement, html } from 'lit-element';
import firstStyles from './firstStyles.lit.css';
@customElement('first-element')
export class FirstElement extends LitElement {
static get styles() {
return [
firstStyles,
]
}
render() {
return html`
<div>${firstStyles}</div> <!-- Succeeded -->
<slot></slot>
`;
}
}
secondElement.js
import { customElement, html } from 'lit-element';
import { FirstElement } from './firstElement';
import secondStyles from './secondStyles.lit.css';
@customElement('second-element')
export class SecondElement extends FirstElement {
static get styles() {
return [
super.styles,
secondStyles,
]
}
render() {
return html`
<div>${super.styles}</div> <!-- Fails -->
<div>${secondStyles}</div>
<slot></slot>
`;
}
}
Acceptance criteria
What the card must do in order to accept it as complete. Acceptance Criteria must be concrete or measurable.
At least <div>${super.styles}</div>
should display the inherited styles.
Note: I am aware that I can manually set, one-by-one, all the properties (inherited and local) and print them altogether.
I think we'll need more information here.
First, styles should be put in static styles
and not in style elements in the render method. While this is supported, it is discouraged in favor of using static styles
, and you certainly should not do both.
Next, there is not yet platform support for directly importing css so it's unclear what this does import secondStyles from './secondStyles.lit.css';
in your setup. If it's importing a string, then to use it in static styles
you'll need to use unsafeCSS
like this:
// in the first element
static styles = [ css`${unsafeCSS(firstStyles)}`];
// in the second element
static styles = [ super.styles, css`${unsafeCSS(secondStyles)}`];
That should just work and you shouldn't need to include the <style>
elements in render.
I am aware of the first one and considering that very much! My only intention and wish is to display the content of the super.styles
on the browser, and this can only be done in the render
method, can't it?
As regards the second one, there is really a new kind on the block who develops reboost
, a dev server which supports LitElement
, and css
import through Lit CSS Plugin
. So, importing a *.lit.css
file and using its content after internally being transformed via css``
tag function is pretty straight and very easy.
In Style Editor I can see both style sheets; so, importing and parsing both lit.css
files is successful, but I cannot display super.styles
since <div>${super.styles}</div>
fails. Any suggestion? TALIA!
If I understand correctly, you're just wanting to display the CSS text of the styles used in the element in a <div>
, just for debug purposes, correct?
Note that styles
is a static property on the class, so you don't want super.styles
, you want this.constructor.styles
. Note that that will run the getter which in your element has both super.styles
and secondStyles
, so just one expression in the template should be able to show all of it.
However, note that you need to use Array.flat
to turn this.constructor.styles
into a flattened array, because lit-html needs a flat array of renderable objects in the expression in the div (and [super.styles, secondStyles]
would result in a nested array, since super.styles
is an array). Nested arrays are supported in styles
, but for rendering text in the template, lit-html needs a flattened array.
So I believe this is what you want:
<div>${Array.flat(this.constructor.styles, Infinity)}</div>
And note that although you're technically passing an array of CSSResult
objects to an expression in the template, which normally wouldn't do anything good, CSSResult
implements a toString
method that returns the CSS text, so it's actually renderable by lit as text, which sounds like what you want.
If I understand correctly, you're just wanting to display the CSS text of the styles used in the element in a
<div>
, just for debug purposes, correct?
That's correct!
Note that
styles
is a static property on the class, so you don't wantsuper.styles
, you wantthis.constructor.styles
. Note that that will run the getter which in your element has bothsuper.styles
andsecondStyles
, so just one expression in the template should be able to show all of it.
It's OK, no problem at all!
However, note that you need to use
Array.flat
to turnthis.constructor.styles
into a flattened array, because lit-html needs a flat array of renderable objects in the expression in the div (and[super.styles, secondStyles]
would result in a nested array, sincesuper.styles
is an array). Nested arrays are supported instyles
, but for rendering text in the template, lit-html needs a flattened array.
<div>${this.constructor.styles}</div>
does work fine for me! I get the CSS text on the browser!
So I believe this is what you want:
<div>${Array.flat(this.constructor.styles, Infinity)}</div>
<div>${this.constructor.styles.flat(Infinity)}</div>
has also worked fine for me!
And note that although you're technically passing an array of
CSSResult
objects to an expression in the template, which normally wouldn't do anything good,CSSResult
implements atoString
method that returns the CSS text, so it's actually renderable by lit as text, which sounds like what you want.
So, in case of <div>${???.toString()}</div>
or let text = ???.toString()
, what is the ???
?
What about the inherited properties (see issue)?
TAL for your time and help!
...
And note that although you're technically passing an array ofCSSResult
objects to an expression in the template, which normally wouldn't do anything good, ...
I think you are not very correct here. Let's get the following imaginary scenario:
I create a component which draws, for example, a vector (velocity, pressure or forces) field. There are three areas displayed;
- the left area which displays the variables which, for you, are the properties. If the variables are plenty, I need a quick way to print all of them instead one by one (${variable1}, ..., ${variableN}). So, access to the properties is very justified and reasonable.
- the center area which displays the drawing, a colorful vector field, for which I have used
css
to make magic tricks -;) - the right area which displays, after beautifying, the
css
in text form. So, if you do not give me access tocss
input how can I retrieve the text, pass it from acss
beautifier and finally display it?
In addition, taking back or giving me back in the simplest form the data/information I have entered (properties or css) is a kind of receipt or proof of operation! Look at your laptop or pc. You plug it and immediately, before switching it on, a led gets lit. You "gave" it electrical power and it returned to you the input in the simplest form of a tiny light. Other system can give you the voltage (440V, 220V, 110V, etc, and frequency 50Hz, 60Hz, etc).
So, in case of
${???.toString()}or let text = ???.toString(), what is the ????
In Javascript, the string representation of an objects is [object Object]
. You can observe this by doing ({}).toString()
.
However, objects can implement a toString
method to customize this output. For example, ({toString: () => 'string representation'}).toString()
.
@kevinpschaaf was noting that CSSResult
which is the output of css...
is an object and therefore it normally would render as [object Object]
except that it has a toString()
implementation that outputs its given css as text.
Hope that helps.
@sorvell So, how do I call/get access into CSSResult
from the interior of MyElement
class? Tia
It's unclear exactly what you're asking. @kevinpschaaf 's explanation seems to provide the necessary info for displaying the text of style rules applied to the element: #1105 (comment).
Based on your comment:
the right area which displays, after beautifying, the css in text form. So, if you do not give me access to css input how can I retrieve the text, pass it from a css beautifier and finally display it?
Something like this should work to beautify the CSS:
render() {
// The CSSResults in the array will be joined as strings automatically,
// but you could call `toString()` on the members of this array if your code requires it.
const rawCSS = this.constructor.styles.flat(Infinity).join('\n');
// beautify and render the css, assuming you implement `beautifyCSS`
return html`<div>${beautifyCSS(rawCSS)}</div>`
}
Hope that helps.
Closing based on the previous response. Please feel free to re-open if additional discussion is necessary.