loading themes based on user input in angular application - css

I'm trying out an angular application where user can select themes from a dropdown and change the appearance of the application using this tutorial
I'm using :host-context
But the themes is not loading and i'm not sure what is wrong in it.
Below is the code
app.component.html
<!--The content below is only a placeholder and can be replaced.-->
<div [ngClass]="theme">
<nav class="navbar fixed-top navbar-light justify-content-center headerColor">
<a class="navbar-brand" href="#">Socxo Themes</a>
</nav>
<div class="content">
<div class="row topClass">
<div class="col">
<select name="seletTheme" [(ngModel)]="theme" (change)="setTheme(theme)">
<option value="default">Default</option>
<option value="one">Theme 1</option>
<option value="two">Theme 2</option>
</select>
</div>
</div>
</div>
</div>
app.component.ts
export class AppComponent {
title = 'app';
theme = "default";
setTheme(themeName:string)
{
this.theme=themeName;
}
}
I'm first trying to themes the navbar
below is the app.component.css
#import "./app.component.1.css";
#import "./app.component.2.css";
#import "./app.component.3.css";
.content{
margin-top:55px;
text-align: center;
}
.topClass{
margin-top:70px;
}
.headerColor{
border:1px solid;
}
In ./app.component.1,2,3.css i have added the css for themes as below
:host-context(.one).headerColor{
background-color: chocolate;
}
:host-context(.two).headerColor{
background-color: chocolate;
}
:host-context(.default).headerColor{
background-color: chocolate;
}
on selecting a option from select the theme variable value changes but the corresponding class doesn't load
Can anybody guide me..

Use of :host-context() is to apply styles to outside host elements. According to the documentation:
:host-context() selector looks for a CSS class in any ancestor of the component host element, up to the document root
In your case you are trying to apply a style to an element inside the same component. You can do this by doing the following,
Create a nav component and move your nav bar code to that.
Put your theme styles of nav component inside that component's style sheet
`#import "../app.component.1.css";
#import "../app.component.1.css";
#import "../app.component.2.css";`
Change your appComponent.html like following,
<div [ngClass]="theme">
<nav-comp></nav-comp>
<div class="content">
<div class="row topClass">
<div class="col">
<select name="seletTheme" [(ngModel)]="theme" (change)="setTheme(theme)">
<option value="default">Default</option>
<option value="one">Theme 1</option>
<option value="two">Theme 2</option>
</select>
</div>
</div>
</div>
</div>
now your code will work with :host-context(), but remember the space after the function otherwise it won't work :host-context(.one) .headerColor. You don't have a space after your function in the above code.
If you only want to change the color of the nav bar by this, you can simply change all your theme style sheets like following,
.one .headerColor{
background-color: chocolate;
}
.two .headerColor{
background-color: chocolate;
}
.default .headerColor{
background-color: chocolate;
}

The solution to your problem is below:
Steps:
Add data member to the class:
classNames="default";
Add the host in the component decorator as below:
#Component({
//Here you need to add host after template property
host:{
'[class]' : 'classNames'
}
})
After that change your setTheme function to as below:
setTheme(themeName:string)
{
//here changing the host (classNames) dynamically
this.classNames=themeName;
this.theme=themeName;
}

Related

Set background color accordion heading

I want to change the color of an accordion depending on status on the current item in the list.
I want to use something like ng-class="{status: item.status}" (where I have testClass: true)
The problem now is that I can't set the color of the whole accordion heading.
<accordion>
<accordion-group ng-repeat="item in items" class="animate-repeat" is-open="status.open">
<accordion-heading>
<div ng-class="{testClass: true}">
<p>Test</p>
</div>
</accordion-heading>
<div class="row">
<div class="col-sm-12 col-xs-12">
<div class="text-content font-size-14">{{item.text}}</div>
</div>
</div>
</div>
</accordion-group>
</accordion>
CSS
.testClass {
background-color: burlywood;
}
Any idea how to solve this?
I found similar problem here, but the solution didn't work for me
https://github.com/angular-ui/bootstrap/issues/3038
fiddle:
http://jsfiddle.net/f8ce1b0w/2/
Apply the class to the 'accordion-group' and then style with css.
HTML
<accordion-group ng-controller='MyAccordionGroupController' class="test" is-open="isopen">
CSS
.panel {
&.test {
& > .panel-heading {
background-color: red;
}
}
}
http://jsfiddle.net/BramG/f8ce1b0w/8/
You'll want to move the applied class higher in the hierarchy:
http://jsfiddle.net/f8ce1b0w/7/
Then your css will look like :
.panel-warning .panel-heading {
//customize your css here
}
The problem is you are placing the test-item inside an item with padding. Instead, place the test-item-class higher up, and then use css to target the items.
If your states will match to Bootstrap states, then you may want the validation class names from here: https://getbootstrap.com/docs/4.0/migration/#panels
(panel-success, panel-info, panel-warning, panel-danger)
These class names are already in your Bootstrap css.
This is the solution to your problem
.test{
background-color: red;
}
.test-parent.panel-default > .panel-heading {
background-color:red;
}
<accordion-group ng-controller='MyAccordionGroupController' is-open="isopen" class="test-parent">
<accordion-heading>
<div class="test">
I can have markup, too!
</div>
</accordion-heading>
This is just some content to illustrate fancy headings.
</accordion-group>

CSS encapsulation with Angular 4 and Materialize

Here's an example that introduces both regular Materialize select and Angular Materialize component:
#Component({
selector: 'my-app',
styles: [`
.select-wrapper {
background-color: red;
}
`],
template: `
<div class="row">
<div class="col s6">
<select materialize="material_select">
<option>...</option>
</select>
</div>
<div class="col s6">
<select class="non-angular-materialize">
<option>...</option>
</select>
</div>
</div>
`,
})
export class App {
ngOnInit() {
$('.non-angular-materialize').material_select();
}
}
Styles are not applied.
Although same example works with /deep/, this defies the purpose of components:
:host /deep/ .select-wrapper {
background-color: red;
}
Why does this happen? Is it possible to keep CSS encapsulation and avoid /deep/ when styling the elements of component template? Is this problem specific to Materialize?
ViewEncapsulation.Emulated is used by default.
To emulated css encapsulation angular addes some attributes to all elements within template.
For example, the following template
<div class="col s6">
<select materialize="material_select">
<option>...</option>
</select>
</div>
becames
<div _ngcontent-c0="" class="col s6">
<select _ngcontent-c0="" materialize="material_select">
<option _ngcontent-c0="">...</option>
</select>
</div>
where c0 is unique id of your component.
And besides overwriting template angular also create specific css selectors from styles|styleUrls content.
So
.select-wrapper {
background-color: red;
}
becames
.select-wrapper[_ngcontent-c0] {
background-color: red;
}
Eventually the CSS is not applied because your dynamically added HTML(after running plugin) doesn't have the attributes _ngcontent-c0 applied
Using the "shadow piercing" CSS combinators or having styles outside of styles|styleUrls properties should work around it.
the use of /deep/, >>> and ::ng-deep are with emulated view encapsulation. Emulated is the default and most commonly used view encapsulation.Angular support 3 types of view encapsulation 1.Native: view encapsulation uses browsers native shadow DOM. 2.Emulated(default): emulate the behaviour of shadow DOM by renaming css classes and effectively scope the CSS to the component's view. 3.None: Angular does no view encapsulation. Angular adds the CSS to the global styles.similar to pasting components styles in html
you can set the view encapsulation by adding encapsultion with your component. eg:-
#Component({
selector: 'hero-team',
template: ``,
encapsulation: ViewEncapsulation.None
})

Styling materialize select with materialize from angular 2 materialize directive

I'm trying to style the input field of the select box that materialize css creates. I'm using the angular 2 materialize directive. This is what my html looks like:
<div class="input-field col s12">
<select id="property-selector" materialize="material_select" name="propertySelector">
<option class="property-option">Address 1, 1000AA Amsterdam, The Netherlands</option>
</select>
</div>
This is what the scss looks like:
#property-selector-card {
font-family: 'Roboto', Arial, Helvetica, sans-serif;
font-weight: 500;
color: #118073;
font-size: 17pt;
div.select-wrapper {
.select-wrapper input.select-dropdown {
border-bottom: none !important;
}
}
}
This generates the following html in the browser:
<div _ngcontent-kld-6="" class="card-panel row" id="property-selector-card">
<div _ngcontent-kld-6="" class="input-field col s12">
<div class="select-wrapper initialized"><span class="caret">▼</span>
<input type="text" class="select-dropdown" readonly="true" data-activates="select-options-95a42e27-1c84-d800-0534-aaaaeb70c462" value="Address 1, 1000AA Amsterdam, The Netherlands"><ul id="select-options-95a42e27-1c84-d800-0534-aaaaeb70c462" class="dropdown-content select-dropdown "><li class=""><span>Address 1, 1000AA Amsterdam, The Netherlands</span></li></ul>
<select _ngcontent-kld-6="" id="property-selector" materialize="material_select" name="propertySelector" ng-reflect-materialize="material_select" class="initialized"
<option _ngcontent-kld-6="" class="property-option">Address 1, 1000AA Amsterdam, The Netherlands</option>
</select></div>
</div>
</div>
Now, I'm having issues overriding the border-bottom style (that I don't want). The selector that I use in scss does not seem to respond.
I've been able to adjust the font by setting it on a parent element, but I get stuck with the select-wrapper element that the materialize js generates and the css selector I use gets overriden as well it seems.
Any idea how to effectively style the input element?
I had the same issue. In my case, I was trying to add the style in the component.style.css file and it did not have any effect, then I tried by adding it to main style.css and it worked.
I think in your case, instead of using id, use class name to traverse through and set style.
.custom-select {
div.select-wrapper {
.select-wrapper input.select-dropdown {
border-bottom: none !important;
}
}
}
and give the classname to the outermost div of select element
<div class="input-field col s12 custom-select">
<select id="property-selector" materialize="material_select" name="propertySelector">
<option class="property-option">Address 1, 1000AA Amsterdam, The Netherlands</option>
</select>
</div>

How to change angularJS's default css styles? Search box etc

Is there a way to change the default styles of AngularJs search box?
<div ng-controller="PersonListCtrl">
<div class="bar">Search:
<input ng-model="query">
</div>
<ul class="" ng-show="query">
<li ng-repeat="person in persons | filter:query">{{person.name}}</li>
</ul>
</div>
</div>
I would like to change the colour and size of the search box and perhaps change the text colour. I've messed around in the CSS but it doesn't seem to be effecting anything.
I've tried
#bar {
background-color: #d7d7d7;
color:#000000;
}
and
.bar{
background-color: #d7d7d7;
color:#000000;
}
AngularJS does not introduces any styles as far as I know. You need to assign the id or the class to the HTML element:
<input ng-model="query" id="bar">
or
<input ng-model="query" class="bar">
You're currently targeting the wrapper of the input, you could just use
.bar input {
instead

Ruby-on-rails Twitter Bootstrap field with error styling

Im using Ruby on Rails 4 with twitter bootstrap to display a form_for (twitter bs form_horizontal). The styling below works correctly (label, input and hint display next to each other ) for normal fields (non error'd) when rails wraps elements in the field_with_errors div however the hint is dropped to the beneath the input element.
<div class="control-group required">
<div class="field_with_errors"><label class="control-label" for="lot_commonname_id">Common Name</label></div>
<div class="controls">
<div class="field_with_errors"><select id="lot_commonname_id" name="lot[commonname_id]"><option value="">Please select</option>
<option value="1">x</option>
<option value="2">y</option>
<option value="3">z</option>
</select>
</div>
<div class="hint">
<a href="#" rel="tooltip" data-original-title="xyz test.">
<i class="icon-info-sign"></i>
</a>
</div>
</div>
</div>
.field_with_errors {
#extend .control-group;
#extend .error;
}
.form-horizontal .field_with_errors
{
margin: 0;
}
.form-horizontal .field_with_errors:before, .form-horizontal .field_with_errors::after
{
display: block;
clear: none;
}
the following jsfiddle http://jsfiddle.net/a78B5/6/ demos the problem
Divs default to display:block so it will naturally drop down to be below your input. Add styling to use display:inline or display:inline-block and it will move back to being next to your text box.

Resources