I am using CSS Modules in an Angular Project with Webpack.
I had already transformed the class names in .css
and .scss
files with postcss-modules.
Then with posthtml-css-modules I had changed the values on the class property in html elements for his hash value defined by postcss-modules
.
I can say that everything is working fine 💪.
Now, I have a new challenge to resolve.
Angular, has a feature that allows you to change dynamically the value of class
in a html element depending on a condition:
https://angular.io/api/common/NgClass
For Example, I can do:
<div [className]="myVar ? 'myClass1' : 'myClass2' " >
If myVar = true
, the html element will be:
<div class="myClass1" >
And if myVar = false
, the html element will be:
<div class="myClass2" >
Like I do not know what is going to be the value of myVar
during compilation time (because the value of myVar
depends on user actions) I am not able to set the value for <div css-module="myClass1" >
or <div css-module="myClass2" >
in order to hash the class names of myClass1
or myClass2
.
BUT (Here comes my solution)...
If I can invoke the same function that does [hash:base64:5]
(https://github.com/css-modules/postcss-modules#generating-scoped-names)
I can create a function that receives a string as parameter and return the class name as a hash.
It would be something like this:
<div [className]="setMyClassNameInHash(myVar)">
Then in javascript:
function setMyClassNameInHash(condition) {
return condition ? doHash64('myClass1') : doHash64('myClass1');
}
doHash64()
would be the function that takes a string and returns the hash using [hash:base64:5]
.
In conclusion, my question is:
¿How I can invoke the same function that does [hash:base64:5] in a javascript file?
Thanks!!!!
You'll need to integrate a templating step into your build process. The plugin exports the class names and their mapped names to a json file, so you can look up the hashed class name from the original.
Edit: Since the built in templating only works for a single class name and doesn't appear to support replacing class names in things like angular attributes, you could do the templating yourself using a templating library like lodash. If you're already using grunt or gulp, I'd recommend using their template tasks instead of this manual way because they do a lot of things for you, like supporting multiple files.
In your html, you would use lodash delimiters to get the hashed class name like:
<div [className]="myVar
? '<%= getHashedClass('myClass1') %>'
: '<%= getHashedClass('myClass2') %>' " >
Your node build script might look like this:
var fs = require('fs');
postcss([
require("postcss-modules")({
// Callback to get hashed class names
getJSON: function(cssFileName, classNames, outputFileName) {
var filePath = '/path/to/outputDir/file.html';
// Function to lookup hashed class names
var getHashedClass = function(unhashedClass) {
return classNames[unhashedClass];
}
// Read your html file as a string
var html = fs.readFileSync(path),
// Use lodash to template it, passing the class lookup function
var compiled = _.template(html);
var templated = compiled({
getHashedClass: getHashedClass
});
// Write the templated html
fs.writeFileSync(path, templated);
}
})
]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With