Reputation: 4252
I am building a NativeScript application with Angular and I am trying to implement Theme switching, but I cannot get it to work with Webpack bundling.
My versions:
7.2.12
7.2.3
2.0.0
3.2.2
I followed the turtorials for implementing the feature in an Angular project: here and here. But these are for non-webpack (without the --bundle flag) builds. With the bundle flag (and the change described here) the switching no longer works and an error is thrown on each switch:
JS: ~/assets/themes/dark.scss
JS: Error: Css styling failed: Error: undefined:1:26: missing '{'
The theme file (located in ~/assets/themes/dark.scss
)
ActionBar {
background-color: #B20000;
color: #FFFFFF;
}
.btn-primary {
background-color: #B20000;
color: #000000;
}
The function applyThemeCss()
should extract the styling from the project, but it doesn't because of an error.
The test project can be found here, on StackBlitz (I didn't use the Nativescript playground, since it doesn't have a package.json and the assets folder )
Upvotes: 0
Views: 1099
Reputation: 4252
With the help of @Manoj, I managed to load my css themes into my application and switch themes.
The line { from: { glob: "assets/**" } },
copies the stylesheets over from 'assets/' to 'dist/assets'.
But since I want to keep all my styling in the same folder ('styles/') I needed to update the code to: { from: { glob: "styles/themes/**" }, to: 'assets/' },
.
And since I am using scss instead of css I still need to convert the styling. We can do this via the renderSync
method of node-sass. (see this post for more information)
When we combine this we get the following code:
const scss = require('node-sass');
....
new CopyWebpackPlugin([
{
from: { glob: "styles/themes/*.scss" },
to: 'assets/themes/[name].css',
transform(content, path) {
const result = sass.renderSync({ file: path });
return result.css.toString();
},
},
{from: {glob: "fonts/**"}},
{from: {glob: "**/*.jpg"}},
{from: {glob: "**/*.png"}},
], {ignore: [`${relative(appPath, appResourcesFullPath)}/**`]}),
This copies and compiles the theme files from styles/themes/
to assets/themes/
. Note that this also ignores any subfolders located in the themes folder. This way we can do the following:
themes/
-- parts/ // <-- This folder will not be copied
---- _dark-variables.scss
---- _light-variables.scss
-- dark.scss // <-- This will be compiled into assets/themes/dark.css
-- light.scss // <-- This will be compiled into assets/themes/light.css
Upvotes: 0
Reputation: 21908
applyThemeCss()
expects CSS text not path to file. In the example code he uses a require statement to read the file then passing the CSS text to the method.
Also in your case if you want multiple themes to be applied dynamically, then you may have to modify your webpack.config.js
to ship the CSS files to app bundle, something like below.
// Copy assets to out dir. Add your own globs as needed.
new CopyWebpackPlugin([
{ from: { glob: "assets/**" } },
{ from: { glob: "fonts/**" } },
{ from: { glob: "**/*.jpg" } },
{ from: { glob: "**/*.png" } },
], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
Then use the applyTheme()
method to pass the file name
Themes.applyTheme(ThemeService.THEME_PATH + theme);
If you like to use applyThemeCss()
then read the file and pass the content
Themes.applyThemeCSS(knownFolders.currentApp().getFile('assets/themes/' + theme).readTextSync(), theme);
Upvotes: 1