templating icon indicating copy to clipboard operation
templating copied to clipboard

[Feature request]: Custom attribute scoped CSS

Open pndewit opened this issue 7 years ago • 14 comments

I'm submitting a feature request

I am not really sure if this is the right project to submit this request in, but I didn't know which one to put it in. I am building an Aurelia adapter for Material Design and this adapter contains both custom elements and custom attributes. For each component I need to include the component's Material Design CSS file and for elements this is easy (using either <require from="..."> or the viewResources decorator). But I would really like to accomplish the same thing for my custom attributes.

pndewit avatar Nov 21 '17 11:11 pndewit

@pndewit and importing css in attribute class does not produce the desired result?

Alexander-Taran avatar Mar 22 '18 09:03 Alexander-Taran

Good point, noticed the css import statements here: http://aurelia.io/docs/tutorials/creating-a-contact-manager#building-the-application-shell. So I tried something similar like: import 'bootstrap/dist/css/bootstrap.css';

But it's not working :(

pndewit avatar Mar 23 '18 08:03 pndewit

@pndewit it should work. how are you bundling/loading?

Alexander-Taran avatar Mar 23 '18 08:03 Alexander-Taran

@Alexander-Taran I now see during my build it is showing the following output (changed paths to the bootstrap example):

------- File not found or not accessible ------
| Location: ....../node_modules/bootstrap/dist/css/bootstrap.css.js
| Requested by: ....../node_modules/some-module/dist/index.js
| Is this a package? Make sure that it is configured in aurelia.json and that it is not a Node.js package
-----------------------------------------------

And as can be read from that piece, I am using Aurelia CLI.

pndewit avatar Mar 23 '18 09:03 pndewit

Using the text loader and injecting the styles myself works:

import mycss from 'text!bootstrap/dist/css/bootstrap.css';

@inject(DOM, Element)
export class MyComponent {
  constructor(private dom, private element:Element) {}

  attached() {
    let css = this.dom.injectStyles(mycss);
    this.element.appendChild(css);
  }
}

Are the docs incorrect? Or am I missing something?

pndewit avatar Mar 23 '18 09:03 pndewit

@bigopon @Alexander-Taran

sorry to comment on a closed issue,

This will work when you know the loader for your css is the text loader, however when writing a plugin which requires to load some css in a custom attribute or element, and beforehand you don't know which loader will be used, you need adhere to the standard means of importing CSS such as import 'mycss.css', that will cause errors when using the built-in bundler and having text loader, for you have not specified text! on your import.

any solutions to handle this?

shahabganji avatar Dec 17 '18 14:12 shahabganji

See aurelia/cli#976

import "some.css" is not a standard JS feature, different bundlers might supported differently. If you are developing aurelia plugin:

  1. in html <require from="some.css"></require>,
  2. in js if no view @noView([PLATFORM.moduleName('some.css')]);

Or use inline css string inside JS file, then do DOM.injectStyles manually. Like https://github.com/aurelia/dialog/blob/ab7e534c94e2be317e56ec3848185932747eaf34/src/dialog-configuration.ts#L48

3cp avatar Dec 17 '18 22:12 3cp

@huochunpeng Thanks for the extra options, but I can't use these in my case. 1 and 2 can only be used for customElements and I am trying to create a customAttribute with some extra styles. Inline CSS string inside JS file in combination with DOM.injectStyles would work, but my customAttribute depends on a CSS component from a third party that distributes a CSS file.

pndewit avatar Dec 18 '18 07:12 pndewit

@huochunpeng

import "some.css" is not a standard JS feature

My bad, I thought it is.

I currently use DOM.injectStyles, and in case of the second approach, I used viewResources whcih does not work properly. I'll give noView a shot, but I remember it works with custom elements and not attributes as @pndewit said. and unfortunately we are also depending on a third party library.

shahabganji avatar Dec 18 '18 07:12 shahabganji

I'll give noView a shot, but I remember it works with custom elements and not attributes as @pndewit said. and unfortunately we are also depending on a third party library.

I just tested it to be sure and it gets ignored. 😞

pndewit avatar Dec 18 '18 07:12 pndewit

I see. It should be doable to implement another decorator which purely brings in css deps. As long as the non-component class is loaded by aurelia DI, it could work.

But I recall a problem with our webpack default setup. aurelia/cli#911 Any css dep, no matter is loaded by <require from="./s.css"></require> (this can be in a @inlineView decorator) or @noView([PLATFORM.moduleName('s.css')]) or import 's.css';, if it is written inside a JS file. Our webpack setup will try to use style-loader to handle it, which injects the css onto html head (we actually only want that behaviour for import 's.css';.

Since css importing is not a standard js feature. No matter how to write the import, for webpack users, it depends on whether they use style-loader, and how they config the style-loader. It is not in the control of the plugin author.

The reliable way is:

  1. use <require from="s.css"></require> in html file. This is irrelavent to your use case.
  2. manually call DOM.injectStyles. That means you need to copy the 3rd party css content to your js file.

Otherwise, do nothing, then instruct the users of your plugin to manually do <require from="3rd/party.css"></require> in app.html.

Hope this clarified some bits.

3cp avatar Dec 18 '18 21:12 3cp

I had seen the issue you mentioned above, I just I have one questions is the built-in bundler using requireJS also depends on webpack? I had the problem with that configuration and not webpack.

Hope this clarified some bits.

That definitely clarified, thanks :pray:

shahabganji avatar Dec 19 '18 05:12 shahabganji

Thanks @huochunpeng! 👍

Otherwise, do nothing, then instruct the users of your plugin to manually do in app.html.

This is what I have been doing for the last year or so. Since I am having a monorepo for Aurelia components (custom- elements and attributes) that is based on another monorepo (also maintained by myself) which contains the actual styles for a Material theme, this is generating quite a long list of imports in the base HTML in some cases. Thus my motivation to search for another solution 😄

Note: I am also using RequireJS.

pndewit avatar Dec 19 '18 07:12 pndewit

Cli requirejs does not use webpack at all. The PR for requirejs setup to support import css in js is not merged yet.

3cp avatar Dec 19 '18 07:12 3cp