How to Load CSS files from within Typescript files

How can I read a CSS file relative to one of my ts files and use DOM.injectStyle?

I kind of write a decorator for that:

export function injectCss(value: string): any {
  return function (target: Function) {

    let container = Container.instance;

    let loader: Loader = <Loader>container.get(Loader);

    let css_id = 'inject_css_' + target.name;

    loader.loadText(value).then(css => {
      DOM.injectStyles(css, null, null, css_id);
    });

    target.prototype.injectedCssId = css_id;

    return target;

  };
}

it works fine when addressing an npm module CSS

@injectCss('npm_package/build/test.css')
export class SomeServiceClass{
}

but not when using a relative path

@injectCss('../../my_resource_folder/test.css')
export class SomeServiceClass{
}

Is there any workaround?

import {Origin} from 'aurelia-metadata';
import {relativeToFile} from 'aurelia-path';

const myModuleId = Origin.get(this.constructor).moduleId;
const absolutePath = relativetoFile('../../my_resource_folder/test.css', myModuleId);

Got the idea from here:

1 Like

The above code is for within component.

Looks like I need to delay the Origin.get in annotation to get it work.

function some(value) {
  return function(target) {
    setTimeout(() => {
      const moduleId = Origin.get(target).moduleId;
      console.log('moduleId: ' + moduleId); // only work after delay
    });

    return target;
  };
}
1 Like

I am to test the solution, I’ll let you know the result :+1:

It is still undefined.

I guess moduleId is for routes and not a plain typescript class, right? Besides, I need the path of the file in the bundle and it might be different than its absolute path in the file system.

Weired, setTimeout worked for me.

moduleId is the module path of any class known to the loader (requirejs/systemjs/webpack).

1 Like

My absolutePath = relativetoFile is not talking about the file system, is about the moduleId in view of aurelia Loader.

Aurelia uses relativetoFile func to get the moduleId before load it.

I should write moduleId = relativetoFile.

1 Like

Curious to know did you find a working solution?

it did not work with moduleId as it is always undefined, however after talking with @jods4 on gitter, and using absolute path the problems sounds to be solved, I test it with fusebox and now I am trying to test with webpack and requireJS, to assure that it will work with either of them.

not yet, only fusebox-aurelia-loader, works fine with what @jods4 suggested. about setTimeout, I am not sure maybe in your case an instance is created and moduleId becomes valid, not sure about life cycle in js, but in my case I didn’t get event one running with moduleId not being undefined. :weary:

I guess you are right, I was testing annotation on component, not a service class. For service, you want to delay it until instantiated.

And another point to mention, components are Aurelia stuff, while services are not, they are plain typescript or to be precise javascript, they might not have moduleId at all; I’ll test it, however.

css tutorial list:

java tutorial
https://javacodegeeks.net/

1 Like