Stimulus controller not registering CSS styles? - javascript

I'm using rails, tailwind, and stimulus together. The application also integrates hotwire, but I'm not sure how relevant that is. Most of the code was written by others, so I don't know what someone could have potentially introduced that could cause this result.
I have html similar to this
<div data-controller="modal" data-action="click->modal#doStuff" data-modal-target="myModal" class="block bg-red-500">
</div>
and a controller
import { Controller } from '#hotwired/stimulus`;
export default class extends Controller {
static targets = ['myModal']
doStuff(){
console.log(this.myModalTarget.style)
}
}
Visually, I can see a red background as expected
If I inspect the html, I can see the appropriate classes and css
but when I click on the div, it calls console.log this.myModalTarget.style and everything in the CSSStyleDeclaration object is empty strings, including display and backgroundColor
At first, I thought it might be a race condition thing. It doesn't fully make sense, but maybe for some reason the controller is getting the myModalTarget before the CSS changes are being applied on the initial page render. But then I modified the controller to this:
import { Controller } from '#hotwired/stimulus`;
export default class extends Controller {
static targets = ['myModal']
doStuff(){
console.log(this.myModalTarget.style)
this.myModalTarget.style.display = 'block'
}
}
After clicking on the div twice, it correctly applies the 'block' style to the div to the point where if I console.log(this.myModalTarget.style) I can see in the CSSStyleDeclaration object that display: block as I expected.
However, the value for backgroundColor is still showing as ""
The entire time, I can visually see a red background, but if I console.log(this.myModalTarget.style.backgroundColor) the result I get continues to be ""
I would think that if this were a race condition like the one I described, the backgroundColor details would be updated and show a value of "red" eventually.
Can anyone see an issue, or at least offer some ideas for what could possibly cause this to happen?
I feel like I've seen this behavior multiple times throughout this application, unfortunately and I haven't been able to figure out for the life of me why the behavior of things are the way they are.

You're confusing two very different things.
Element.style:
The style read-only property returns the inline style of an element in the form of a CSSStyleDeclaration object that contains a list of all styles properties for that element with values assigned for the attributes that are defined in the element's inline style attribute.
And inherited CSS rules from CSS files or tags which are available through Window.getComputedStyle().
import { Controller } from '#hotwired/stimulus`;
export default class extends Controller {
static targets = ['myModal']
doStuff(){
console.log(window.getComputedStyle(myModalTarget).display)
this.myModalTarget.style.display = 'block'
}
}

Related

Vue 2 - Styling HTML returned in a switch statement

I'm building a generic component supposed to receive various backend data. I wrote a switch. One condition is :
case 'Bases':
let bases = variant[tableName][colValue].map((base) => {
return `<div class="base b${base.strongestIndication}">${base.name}</div>`
})
return bases.join('')
I use v-html in my template, therefore in this case, we have 3 divs created, each with a class of "base" and then "b1", "b2", "b3". I can see on the webpage that these classes are properly set when I inspect the elements.
I've described in my style some rules for theses classes (mostly background-color, border-radius and so on), but they do not apply.
I'm guessing this might have something to do with the CSS being applied before these divs are created but I'm not sure of this.
What should I do to get these tags created by JS to be styled properly ?
(Also, I know using v-html can be dangerous, therefore if you have a better idea for this whole thing, I'm all ears)
There is no need to build the markup in component methods. Define it in template and bind the classes dynamically. Since you didn't post the api data structure, neither how you are using this snippet of code, I can only refactor the specific case.
<div
v-for="base in colValues"
:class="['base', `b${base.strongestIndication}`]">
{{base.name}}
</div>
Figured it out. For those wondering, switch statements returning html code aren't styled if the tag in your file is scoped. Unsure why, but removing scoped work. If you decide to do so, but unique class names, as these styles will spread all throughout the application !

Modifying or adding classes to individual components within core wordpress blocks

I am having difficulty modifying or adding additional classes to individual components of wordpress blocks. I essentially just want to add a class or classes to some of the pieces that make up some of the core wordpress blocks to do things like add bootstrap styling.
An example of this would be the image gallery block. It works well enough for my purposes, but I may want to do something like add an "img-fluid" or "img-thumbnail" class to the images that are within that gallery.
I have looked through the documentation for block filters and I feel as though my answer is going to lie somewhere in there, I'm just not sure where yet.
I have tried using the blocks.getBlockDefaultClassName filter, but this adds a classname to the entire block as opposed to individual pieces that make up that block (such as the images in my gallery example).
This is the example they give for it in the documentation:
// Our filter function
function setBlockCustomClassName( className, blockName ) {
return blockName === 'core/code' ?
'my-plugin-code' :
className;
}
// Adding the filter
wp.hooks.addFilter(
'blocks.getBlockDefaultClassName',
'my-plugin/set-block-custom-class-name',
setBlockCustomClassName
);
I feel as though blocks.getSaveContent.extraProps might do what I need it to, but I am not sure how to use it in this way. The example they use looks like this:
function addBackgroundColorStyle( props ) {
return lodash.assign( props, { style: { backgroundColor: 'red' } } );
}
wp.hooks.addFilter(
'blocks.getSaveContent.extraProps',
'my-plugin/add-background-color-style',
addBackgroundColorStyle
);
But even if I were to add an extra property like a class name, I would think I would then need to modify the actual save and edit functions (I guess using more block filters) to then use that class name when it displays those pieces (in this case - the images), and I'm also not sure how to do that.
Any thoughts or suggestions about this would be appreciated.
There are two kind of changes one is structural change and the other one is styling change. In your scenario you need styling change but you are actually looking for structural change. You can write your own CSS that can handles your block styling on editor view and on front end.
These are the hooks that you need to enqueue your styles enqueue_block_editor_assets (enqueue your styles only on backend editor) and enqueue_block_assets (enqueue your styles on both backend and frontend).

Polymer `<custom-style>`: which line of code stops appending to DOM multiple imports of the same custom-style template module?

My project's upstream web components theme is implemented as <custom-style> elements link
I want to implement my document level overrides as a JS module (as in, avoid hardcoding into app index.html or equivalent), which on surface looks simple:
import '#vaadin/vaadin-lumo-styles/color.js';
const $template = document.createElement('template');
$template.innerHTML = `
<custom-style>
<style>
html,
:host {
--lumo-primary-color: red;
}
</style>
</custom-style>`;
document.head.appendChild($template.content);
QUESTION
Some web components used in the document also import original theme via import '#vaadin/vaadin-lumo-styles/color.js'.
I want my overrides to always cascade last (without !important hacks).
Do multiple later import '#vaadin/vaadin-lumo-styles/color.js'; calls have any potential to revert my CSS custom property overrides cascade?
Think:
original: --lumo-primary-color: hsl(214, 90%, 52%);
me: import original, override --lumo-primary-color: red;
later: can a later import of original "reset" cascade back to --lumo-primary-color: hsl(214, 90%, 52%);)?
ES6 import a file in multiple place, why the file loads once? seems to imply maybe not, but I'm struggling finding any documentation that explicitly states something one way or another about <custom-style>.
Perhaps https://github.com/Polymer/polymer/blob/v3.2.0/lib/elements/custom-style.js#L80 is the key?
GLITCH
https://glitch.com/edit/#!/roan-pizza?path=src/index.js seems to confirm repeated imports don't seem to cause a problem, but why? Is it purely due to ES6 module load caching, or is there something else to it?
EDIT drag-n-dropping <custom-style> elements around in browser inspector definitely has an effect on the cascade (colors change based on tag order), so at least loading order is confirmed to matter.
Tips: remove all for edit.
difference tags (of <custom-style>) by #id => <custom-style id="id01">.
save <custom-style> to edit => save(#id).
red (in "--lumo-primary-color") is a variable => var color = red.
remove all content of a <custom-style id="id01"> => remove_all(#id).
add a new content you need => as you did above.
I just hope that you will solve your problem. You are better than me so I will not write code.

Style through components not created

New question:
So, im looking for a way to toggle the display of two css classes called hotel-in and hotel-out.
These two classes will be in all of my 22 components.
To toggle the display, im using a variable called inHotel that contains wherever the user is in a hotel or not.
when the variable is true, the hotel-in will be visible, and hotel-out be hidden.
when the variable is false, the hotel-out will be visible, and hotel-in be hidden.
How can i achieve this in the best manner?
Is it something general i could do in my main controller, that loads all the components?
Or do i have to do something spesific in every of the 22+ controllers?
Old question:
IN My main app component, where i have router outlets, i have the following:
<style *ngIf="inHotel">
.hotel-in {
display:block;
}
.hotel-out {
display:none;
}
</style>
<style *ngIf="inHotel == false">
.hotel-in {
display:none;
}
.hotel-out {
display:block;
}
</style>
but when checking, even when that the inhotel is false, it dosent create that style.
The idea is that a function will toggle this inhotel.
and everything within the other components will have a div class hotel-out and hotel-in . and that will be visible/invisible depending of the inhotel class / style .
But for some reason it wont work.
What do i need to do to make this work?
edit 2:
I could use ngclass as mentioned, and get the hotelstate by every controller/route.
But in PHP and angular1, i had the option to put that piece of style code in the main file, ( where the router-outlet is located), and it would work as supposed.
The ideal would be that i only one place changes the display of hotel-in and hotel-out to toggle display none and display block.
then everything that had hotel-in and hotel-out in the other routes/views would act according to id.
edit3:
an example of html style that would be in different routes.
<div class=hotel-in">You are in hotel , more html...</div>
<div class="hotel-out">Something completely diff here </div>
edit3:
even when im style *ngIf, it wont produce any acual tags with content on the page.
edit4:
It seems like i cant even post a style tag in the angular/angular-cli html. how come? and how can i make so i can make the style tag?
for some reason, even this wont come up to the page.
<style>
.test {
color:black;
}
</style>
You see change the style rules if they are written inside html page itself using https://github.com/deanmcpherson/angular-inline-style.
The idea is to rebuild style rules each time scope changes, by default this functionality is not provided by angular. But we can write a directive that links to style tag and recompiles it based on scope.

Error with place holder on jsx

I have a simple react HTML input component and as it used on different sections/pages, I added some props for styling it and its placeholder. The problem is that sometimes I got an error on the compilation(we are using nextjs).
This the code:
{placeHolderColor && (<style jsx>{`input::placeholder{color:${placeHolderColor}}`}</style>)}
Basically, I'm using an inline If with Logical && Operator inside the render function to check if the prop placeHolderColor exists, and if exist add the style tag.
The error I'm getting:
Warning: Unknown prop jsx on tag. Remove this prop from the element.
The error only occurs when you reload the page. If you made a change and the hot code reloading run, there is no error. Not sure if the problem is the var inside the literal, the '::placeholder' pseudo-element or what. The code works anyway, and if the placeHolderColor var is defined the style is applied.
When I tested your code I got the same error(also on page load). After that I talked to a styled jsx dev with nickname #g (on github #giuseppeg) on ZEIT's #next slack channel https://zeit.chat/ and he confirmed that the conditional use of <style jsx> tag is not supported. Here is his explanation https://github.com/zeit/styled-jsx/issues/233.
Also, after removing conditional and just inserting your tag like this:
<style jsx>{'input::placeholder{color:${placeHolderColor}}'}</style>
I've got this error:
Module build failed: SyntaxError: Expected placeHolderColor to not come from the closest scope.
Styled JSX encourages the use of constants instead of props or dynamic values which are better set via inline styles or className toggling. See https://github.com/zeit/styled-jsx#dynamic-styles.
According to recommendations from https://github.com/zeit/styled-jsx#dynamic-styles, you basically should not add dynamic values into template literals inside <style jsx> tag (though you can put there constants and constant expressions starting from version 1.0.4 (see UPDATE at the bottom of the answer for details)). The reason behind the prohibition of using props/dynamic values, according to #giuseppeg comment in the slack thread https://zeit-community.slack.com/archives/C2U01UYEA/p1496928897076534, is following: "at the moment styled-jsx compiles and produces static code and therefore the hashes that make the final CSS unique won't change when the value of a variable like color changes"
So, as you see from documentation, it is recommended to use dynamic values via inline styles or className toggling. Unfortunately, styling pseudo-elements (placeholder etc.) in not possible via inline styles in React, so if you have finite number of possible colours then create a class for each colour case and use it like this:
const InputWithColouredPlaceholder = props => (
<div>
<input
placeholder="text"
className={
'placeholderColourClass' in props && props.placeholderColourClass
}
/>
<style jsx>{`
.reddy::placeholder {
color: red;
}
.greeny::placeholder {
color: green;
}
`}</style>
</div>
);
and render it like <InputWithColouredPlaceholder placeholderColourClass="reddy" />
It gets more complicated in case of large range of possible colours though. In this case I would recommend to ask for suggestions in #next channel on ZEIT's slack https://zeit.chat/.
UPDATE
Using constants and constant expressions in template literals should work in styled-jsx 1.0.4 (but nextjs currently depends on 1.0.3, and separate installation of styled-jsx will not help, so wait for update of nextjs to support styled jsx 1.0.4). It means that any constants that are not passed trough props and not created inside component should work (for example you can have a js file with constants for colours and import them into your input component). But it does not fit your case because you need a dynamic way.
I got error Warning: Unknown prop 'jsx' on <style> tag. Remove this prop from the element. For details, see FB react-unknown-prop. What does that jsx property in your style tag means? Just remove it?

Categories