Attempting to follow the guidelines for styling my own components based on Material, but simply can't get it to work, I am doing the following in the scss but it does not work. Importing theming and palette into my scss results in $primary not being found. What could I be doing wrong ? Am I not importing correctly ? How do I correctly import theming in my scss such that I can theme my own components.
At the top of my scss
@import 'node_modules/@angular/material/core/theming/_theming';
.someClass {
background-color: md-color($primary);
color: md-color($primary, default-contrast);
// color: red;
}
Then I get the following on compiling the SASS
Error: Undefined variable: "$primary"
Need Help
#### What is the expected behavior?
Need to be able to correctly theme my own components using material import via my scss
Can't find $primary
Tried to pull together a plunker based on a material seed, find it here
The plunker simply will not render if the code in myComp.component.scss remains as is, if the component theming is removed with the import commented and simply setting the color to red, the page will render correctly ???
Styling my own components based on material
Ng 2.0 final
Material Alpha 9
no
I think $primary is some kind of palette and you can't use it directly to get a value out of it.
In my code for example:
$primary: md-palette($md-blue);
To get a value out of it, you have to get a value out of the Sass Map of this palette:
background-color: map-get($primary, A100);
To find the available palettes, look into the appropriate scss file in the Material dependency folder.
@dahaupt Sorry disagree with that, I am simply am following the guide, this can be found in the docs theming md file, took the code the section "Styling your own components". Therefore this should work, problem is it is unclear how to do this properly.
@HeavenlyHost Okay, maybe I was on the wrong way. But inspecting your plunker example, your own theme is uncomplete.
Just this one import is not enough to define an own theme.
@import 'node_modules/@angular/material/core/theming/_theming';
The docs theming.md readme describes some more stuff to do in Defining a custom theme. Currently, your sass-file has no $primary variable defined. I think in current state, you have to define your own theme in ordner to style your own components and to access those sass variables.
@dahaupt so are you saying that I need to create my own theme in order to theme my own components ? This is not my interpretation of the md file ! It reads as if all I need to do is import theming support and use the existing parameters ? If all I want to do is use an existing prebuilt theme and tap into the existing $primary palette how is this achievable. I do not agree that we should have to create a new theme, can we not simply apply an existing one and how do we do this ?
@HeavenlyHost Yes, for the moment I think it only works the way I described it. But you are right, it should work the way you want to use it. To use the "default" theme, I think we first have to set one theme as our default theme.
The theming seems to be really new, I don't know really much more about it. Let's wait for an answer of a dev.
I've made a PR #1385 that explain a little more about theming custom components. I do not know if it is the better way of doing this but is the way I've found.
@vinagreti I did try what you suggest but I get the following...
node_modules\@angular\material\core_core.scss
Error: It's not clear which file to import for '@import "overlay/overlay"'.
Candidates:
overlay/overlay.scss
overlay/overlay.css
Please delete or rename all but one of these files.
on line 4 of node_modules/@angular/material/core/_core.scss
@import 'overlay/overlay';
Just to be clear, I am not attempting to create a theme, but simply extract the existing $primary value from the current material theme and then have this value overridden by including a prebuilt css into my app, this way all we need to do is import a different css for a new theme in the index.html
Second I don't really want to create my own theme at this time (although long term this will happen), but I do want my custom component to inherit whatever the standard material widgets are using, is this possible ?
Third, your solution means that we would need to create our own theme, is there not a function to extract the current material theme from the core, instead of creating our own via mappings ?
@import 'node_modules/@angular/material/core/theming/all-theme';
@import 'node_modules/@angular/material/core/theming/theming';
@include md-core();
$primary: md-palette($md-indigo);
$accent: md-palette($md-pink, A200, A100, A400);
$warn: md-palette($md-red);
$theme: md-light-theme($primary, $accent, $warn); <-- CAN WE NOT GET THIS FROM MATERIAL, E.G. Get-Current-Theme() which shall return the material theme in use ???
@include angular-material-theme($theme);
@mixin my-core-styles($theme) {
// Extract theme variables
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
$background: map-get($theme, background);
$foreground: map-get($theme, foreground);
}
@import '../core/my-core-styles';
@include my-core-styles($theme);
@HeavenlyHost if you look at the pre-built themes you can see that they call the method @include angular-material-theme at the end of the file to apply the theme to the material components. You have to do the same, because the components have no theme by default.
In the last version, you need to apply one of the pre-built themes and you have two ways of doing this. One is importing the pre-built-theme.css directly in your app-wide style.css and the second is including the pre-built-theme.scss in your app-wide 'style.scss' (if you are using angular-cli, you have a third way that is including the pre-built-theme.scss in angular-cli.json styles list).
So, you have to apply a theme being it your custom theme or some of the pre-built ones. And in that moment, you can customize your components as well, like I showed in the theming.md.
I do not think that would be possible to you to just get the current primary variables because it is not a persistent variable and it exist only in the moment that the @include angular-material-theme($theme); is called. Because of that, you have to create a custom sass function that apply your theme to your custom components. Remember that you can use a pre-built theme instead of creating your own.
About the overlay problem, I think you may be loading the overlay css in other place and it is causing this conflict. You do not need to load any css/scss besides the theming one.
Like I said, I do not know if it is the right or better way of doing this, but is the way I've found that do not stopped me to customize my components based on the current theme, even working with multiple themes.
Are your custom components within the "APP" project as mine are consumed from an external library, think of them as assets that are making use of the Material stuff but with custom functionality. This being the case, do you believe that this should still work, or do I need to do something else ?
The thing regarding the overlays, I do not believe that I am loading the overlay stuff seperately, it fails on the SASS build ?
About overlay, I do not have this issue here. Without see your app I cannot figure out why this is happening.
About custom components. Angular creates one CSS file for each component an it have all styles the component needs to render within or without material design being used in your app. The sass functions just allow you to create theese css files using some of the material design styles and theme. So, once your component is built, you can use it anywhere, even in applications that does not use material design.
The sass functions just help you build the css file for your custom component and not styles it directly.
If you are serving your custom component as a separeted package, you will have to give to the user the power to customize its theme. As it is not in the @angular/material theme, it will not use the material theme unless you tell it to use, that is the reason why we have to create the sass function @mixin custom-input-theme($theme) for customizing our custom components.
In my point of view, you can create a standalone component, that has its own theme and give the user the possibility to customize it using material themes or any theme that you want (bootstrap, foundation...)... but you will have to tel your custom component how to use these themes.
In short, you are creating custom components that uses material theme and not custom @angular/material components. So, you will have to apply the themes somehow...
@HeavenlyHost I think I've found the reason of the overlay problem. In the my-core-styles.scss you are importing @import '~@angular/material/core/theming/theming';. This is not necessary and you can remove it. You only need the @import ~@angular/material/core/theming/all-theme'; file.
And in your my-widget.component.scss you have to import both @import '../core/my-core-styles'; and '~@angular/material/core/theming/theming';` so you can use the variables from your custom theme and the functions from angular material that apply your theme.
I've updated the PR with a more concise example.
So I have attempted to go back to basics and simply try and create a custom theme using the documentation, building the scss with gulp-sass and node-sass. The scss file uses exactly the same code as the example i.e.
@import 'node_modules/@angular/material/core/theming/all-theme';
// Plus imports for other components in your app.// Include the base styles for Angular Material core. We include this here so that you only
have to load a single css file for Angular Material in your app. */
@include md-core();// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue.
$primary: md-palette($md-indigo);
$accent: md-palette($md-pink, A200, A100, A400);// The warn palette is optional (defaults to red).
$warn: md-palette($md-red);// Create the theme object (a Sass map containing all of the palettes).
$theme: md-light-theme($primary, $accent, $warn);// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($theme);`
unfortunately I get the same error on both gulp-sass and node-sass...
{
"status": 1,
"file": "node_modules/@angular/material/core/_core.scss",
"line": 4,
"column": 1,
"message": "It's not clear which file to import for '@import \"overlay/overlay
\"'.\nCandidates:\n overlay/overlay.scss\n overlay/overlay.css\nPlease delete
or rename all but one of these files.\n",
"formatted": "Error: It's not clear which file to import for '@import \"overla
y/overlay\"'.\n Candidates:\n overlay/overlay.scss\n overl
ay/overlay.css\n Please delete or rename all but one of these files.\n
on line 4 of node_modules/@angular/material/core/_core.scss\n>> @import 'ove
rlay/overlay';\n ^\n"
}
I simply can't build a custom theme, irrespective of custom component requirements, what is going on ?
You can test this by taking the above code and building the sass using gulp-sass v2.3.1 and node-sass v3.7.0, Material2 Alpha 9.3 and Angular 2.0 final
Can you show us your Gulpfile?
I think you need to define the extension that the gulp will search for. If you look the error, you can see this message:
It's not clear which file to import for '@import "overlay/overlay"''. Candidates: overlay/overlay.scss & overlay/overlay.css. Please delete or rename all but one of these files.
What it says is that when you call @import "overlay/overlay" the sass compiller does not know if it should load css or Scss file. You need to somehow set your gulp to use only scss files.
Maybe this SO can help you
Did you try it in node-sass, you don't need to worry about Gulp, as stated it fails to build even using this ???
I did not try to run the sass task. I've just looked at your Gulpfile and the output error so I've seen that the error is that your compiler does not know if it needs to compile the scss or the css version of the overlay file.
Now, you need to figure out how to configure your sass task to search only for scss files. If you can do this, the conflict will stop.
Based in what you told us, that the problem is occurring in both gulp-sass and node-sass, so I think the answer works for both.
Also believe this to be related #887
I believe that this is a problem with libsass and is not being fixed officially until v4.0, so the work arround I found was to provide an importer function and massage the file paths to use scss instead of css as follows...
gulp.task('compile-sass', function(){
var sourceSassFiles = [
config.allSass
];var sassimport = function(url, previous){
var filepath = url;
if (!filepath.includes(".scss") &&
!filepath.includes(".css")){
filepath = filepath + ".scss";
}
return {file: filepath};
};return gulp.src(sourceSassFiles)
.pipe(sass({importer: sassimport}).on('error', sass.logError))
.pipe(gulp.dest(config.tsOutputPath).on('end', function(){callback()}));
});
Running into the same overlay issue with node-sass. The problem is that if you don't specify an extension in an @import statement, and there is both a .css and .scss file in the folder, the problem will occur. Since the overlay.css is empty (except for a sourcemap statement), is that file necessary?
Why is the .css needed in the first place? Angular includes the component css in each component and by importing the _theming.scss you generate your own themed .css with all the styles.
Isnt it possible to just remove those from the build?
It is meant for those who are not using sass.
If you are using sass, I think you can remove it by yourself.
The problem with overlay is fixed in #1544- other than that, I think everything else should be covered by https://github.com/angular/material2/blob/master/docs/theming-your-components.md
@jelbourn
Link is broken
@crosshopes New link for the theming guide is at:
https://github.com/angular/material2/blob/master/guides/theming-your-components.md.
Also available here:
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
Also believe this to be related #887