Create dynamic class with Angular - css

I'm trying to add a dynamic class in Angular template and set a style attributes accordingly.
HTML would be -- <body class="{{ product-id }}">
CSS would be --
product-id : { color: #ccc; }
Where product-id would be a dynamic value.
What would be the best method to do this? I want to be able to have this be a selector I could use for various element locations within the page which is why ng-style isn't working for me.

I think the best approach for what you're looking for is the ng-class directive which allows you to set different dynamic classes based on $scope variables.
You can check out the docs for ng-class here.
Hope that helps you out!

Related

set value of css variable condition wise

I am trying to change value of CSS variable based on another variable. I want to check if current value of variable is white then set it to black...
In some class suppose my variable is --default-var, value of --default-var can be any color....
If value of default-var is white then change it to black
i tried
.my-class{
#if var(--default-var) == #fff{
--default-var : #000;
}
}
I have also tried
.my-class{
#if --default-var == #fff{
--default-var : #000;
}
}
both cases are not working..please help.
Best practice here is to create two classes with the different CSS values and then toggle the class using logic such as in C# Razor or Javascript. This keeps it cleaner to read.
You can not use this kind of Logic in CSS. There are workarounds though.
Use a Preprocessor
You could use either SASS or Less to create CSS-Files that are created conditionally based on variables that you can set yourself. This however only helps if you´re decision is made on build-time. So this will not help you if you want to react to user input.
This is not entirely true, as there are some pseudo selectors that in the end can change styles based on user input. However, you can not use them to react to variables set in your CSS.
Use Javascript
With Javascript you can manipulate elements and their style-Property or their class-List directly. In order to control under what condition you want these changes to be made you can use all the tools that you have in Javascript.
You could read what value your css variable has and then change styles on other classes based on that value.
Just Google for js DOM manipulation or setting css with js. In order to provide better ressources i´d need some more information on what exactly you want to do. This may be what you are looking for: https://stackoverflow.com/a/51860936/11930769.

How to use :host-context selector in an ngClass condition?

I want to set a class active on a div (part of a component) if a variable is true (workspace.active here) AND an ancestor element has class .home.
Something like:
<div [ngClass]="{'active': workspace.active && ':host-context(.home)', }">
Can I use somehow this pseudo selector :host-context in such an conditional expression for ngClass ?
Details:
I want to use same component in two use cases. Only some css properties should be different on the two cases. So I want to customize a css class set on a div on my component based on decision: "there is an ancestor home in the dom tree or not" - this should differentiate the two use cases.
I could do things like this in css:
:host-context(.home) .active {
background-color: #405976;
}
but then all selector combinations containing .active class should be combined also with :host-context and I I don't want to grow the complexity in css as it is already complex.
I would prefer to just set the class .active based on the condition. In css file !, not in code. (This is why :host-context exists in the end.)
In angular you should not make any logical decisions in the code based on the html content properties such as classes or attributes, but vice versa - you should render classes and attributes in html based on data bindings. That's the main idea of angular - rendering view based on data bindings. Component's code should not really care too much about view structure.
So, in this case if your class should be based on some external information you need to #Import() that data through data bindings into your component and then use component properties in the ngClass directive. Yes, it moves logic into the component instead of html/css, but that's where it's supposed to be anyway: in the model/controller code, not in the view markup. Also, this way it will be much more convenient to test such a component.

How to dynamically set complex CSS of an Angular 2+ component?

I'd like to ask for a little nudge to get my brain out of the box I got it into.
Context
Angular 4 using Angular CLI and AoT.
All methods mentioned in https://angular.io/docs/ts/latest/guide/component-styles.html describe ways to set complex CSS of a component while it is being written by a developer.
After a component is created, Angular allows to adjust individual styles and even assign various CSS class names to tags in the component as you please, all that using [ngClass], <div [class.something]="condition">, various #HostBinding decorators and some other methods.
However, none of the above can change the CSS declaration the component is using. The methods above can either (a) use what is already available in the stylesheet defined by the developer or (b) set individual CSS properties to individual HTML tags in the component's template.
Question
How would I update the CSS for the whole component on runtime so that all elements in that component respond to the new CSS?
Say I introduce a new style for a div.someClass and I want all matching elements div.someClass to reflect the new style.
Plunker
A showcase of my attempts is here: https://plnkr.co/edit/N2C40cSb7hd1AyOxWWdT
The button should be red, based on the value of MyChildComponent.styles
I think I understand why it doesn't work the way I would expect: shortly said, styles are built in the component during compilation, not runtime, including those found inside <style /> tags in the template.
But knowing why it doesn't work doesn't help me to make it work.
Any help highly appreciated.
Solution 1
Inserting a new css class is not possible ( as far as i know ) but you can insert css properties to your component dynamically.
I modified your dynamicStyles() to this
get dynamicStyles(): any{
return {'background': 'red' };
}
that returns an object instead of string because you will pass this object to ngStyle of your button.
In your template, I change the button like this
<button type="button"
[ngStyle]="styles">
Button
</button>
Here's a plunkr
Solution 2
This is something that I would not recommend but in your case it might be useful. You can add this
encapsulation: ViewEncapsulation.None
and the import
import {ViewEncapsulation} from '#angular/core'
to your #Component.You can leak your component's css so that you can use it on your child component. Then in your child component, add a [ngClass] in your button so that you can just pass a variable via #Input() if it should be red.
<button type="button"
[ngClass]="{'redButton': isButtonRed}"
>Button</button>
And in your style.css
.redButton{
background:red;
}
And in your main component.
<div>
<h2>Hello name</h2>
<my-child [isButtonRed]="true"></my-child>
</div>
Here's another plunkr
Hope this helps.

Using BEM CSS with Angular Directives

I've been using BEM style CSS to style my angular directives and usually use replace: true to so that my Block level class can be on the "root" of the custom element. This makes it so that I can write all my CSS primarily with classes.
However, replace: true sometimes causes issues (having two ng-if, etc...) and is now marked as deprecated. So I'm starting to try to stay away from replace completely.
But now I'm having trouble applying BEM to these elements that have an actual custom tag the DOM -- now I have to use a tag name instead of a class name, which means I can't really use BEM anymore (since I'll have to use the tag name since I can't apply classes directly to my element in my template). Additionally, using modifiers on my custom element now seems impossible, as does using sibling CSS selectors.
Here's an example that hopefully will illustrate what I mean:
The directive:
angular.module('my.module')
.directive('customElement', function() {
return {
restrict: 'E',
scope: {
isSpecial: '='
},
template: '<div class="custom-element" ng-class="{\'custom-element--special\': isSpecial"></div>'
};
});
The CSS:
.custom-element {
background-color: white;
}
.custom-element--special {
background-color: red;
}
.custom-element--special + .custom-element--special { // this won't work without replace: true
background-color: blue;
}
If I use replace: true everything works as expected (but then it comes with its own headaches).
If I don't use replace, the classes are not applied to the root custom element so the child selector doesn't work.
I could always add classes to the element in the postLink function, but that makes the template much less clear.
Does anyone have any experience using BEM with angular and using classes instead of tag names in your custom directives? What did you do to solve this problem?
i known it's a problem having replace:false for readability purpose.
The actual problem is that we need our OOCSS but you are handling Angular Components with custom tags has CSS Objects, and is not the case.
There is no practical solution for this, i won't recommend you to start adding classes on postLink function.
However what we are use to do is treat the custom tag as is own CSS Object besides the inner object structure. Forcing us to implement an extra CSS class for the custom tag.
block-context
block-context__element
custom-element
Why doing this when block-context__element is a redundant' class?
Because the rest of your BEM structure is the one you will maintain, the custom-element block should have meaning by it self and the block-context__element element is no expected to, you should abstract the CSS Objects from the directive's implementation, if you in some point start changing your html components your classes should still apply.
I hope this answer helps you

how to add background color to input text if it is a dojo datepicker?

I can't set the background color (or border color) of an input text, if it is a dojo datepicker.
My dojo datepicker is an input text with the two additional attribute:
dojoType="dropdowndatepicker"
displayFormat="yyyy-MM-dd"
I assume dojo has its own style, so even if I provide a style that specifies the background color, dojo overrides it.
something like this does not work:
<input type="text" ..other attributes.. style="width:5em;border:solid #FF0000;">
Any help is appriciated.
And may I just add that my dojo version is old as dirt ( will be upgraded) but currently I can't take advantage of the newer features like dijit, etc.
Dojo uses templates for most of their widgets. The HTML code you write (with dojoType attributes and stuff) is nothing more than a placeholder to configure your widget. Inline CSS applied to this HTML will be applied to the top level of your widget.
Your widget usually consists out of multiple HTML elements and so it may happend that the CSS you write inline, will not be applied to the correct element. Also, Dojo indeed uses themes (wich you usually define as a class="themename" on a parent tag (usually <body>) and most default themes of Dojo are using !important CSS lines for various features.
The best way is to inspect what HTML elements are created when you use a widget and to define a style on that specific element. But because the CSS attributes of the Dojo themes are using !important, it's recommended to be more specific than what they define. The easiest way is to add a custom classname to the <body> tag, for example:
<body class="claro custom">
</body>
Then define your style like:
.custom .dijitTextBox > .dijitInputField {
background-color: yellow;
}
.custom .dijitTextBox > .dijitArrowButton {
background: red;
}
I also made an example JSFiddle.
Have a look at this thread - i think this could help you out:
Changing default style of DOJO widget
Regards
add !important to the end of your rules:
<input type="text" ..other attributes.. style="width:5em !important;border:solid #FF0000 !important;">
This should apply stuff to the input. Please check if the element isn't replaced when dojo starts using it and if you are applying the style to the correct element.

Resources