I am using Angular CLI. Actually, I have a menu list. And I would like to change the background color of <li> when I click on it.
I send id to functionchangeColor(). But the problem is I am getting menuButton as null. Please help me to do so.
.html
<ul>
<li id="menu_btn" (click)="changeColor()" >
</li>
<li id="menu_btn" (click)="changeColor()">
</li>
<ul>
.ts:
changeColor() {
let menuButton = document.getElementById("menu_btn");
menuButton.style.backgroundColor = '#816587';
}
The more angular way to do this is define your menu list in an array
// component.ts
menuList = [
{
name: 'Option 1',
isSelected: false
},
{
name: 'Option 2',
isSelected: false
}
];
Then use an ngFor to render the list and use ngClass + each menu items isSelected flag to toggle a selected class.
// component.html
<ul>
<li *ngFor="let menuItem of menuList" (click)="changeColor(menuItem)"
[ngClass]="{'selected': menuItem.isSelected}">
{{menuItem.name}}
</li>
</ul>
// component.css
.selected{
background-color: #816587;
}
Now have your changeColor method handle the toggling of the isSelected flag
changeColor(menuItem){
// toggle off all selected menu items
this.menuList.forEach(item => {
if(item.isSelected){
item.isSelected = false;
}
});
// select clicked menu item
menuItem.isSelected = true;
}
This way angular is handling all of the DOM manipulation. Here is plnkr demonstrating this functionality (https://plnkr.co/edit/NEnzKZ84M85mErYGLE1Y?p=preview)
You can use ngStyle to do this:
<li id="menu_btn" (click)="myStyle = {'background-color': #816587}" [ngStyle]="myStyle">
Related
I need to set active class to one of the many options, which is coming from API. Also the first option is active at first, and when user clicks it has to toggle.
Below is my template :
<div #click="showTimezone">
<span>{{defaultCountry}}</span>
</div>
<div id="timezone-menu" class="timezone-menu" v-show="showTimezone">
<ul >
<li class="country-menu-item" v-for="item in Options" :id="item.id" :key="item.abbrevation" #click="selectCountry(item)">
{{ item.optionText }}
</li>
</ul>
</div>
I stored the data from API in Options array.
data() {
return {
defaultCountry: "CST",
Options: [],
}
}
On the drop down, the CST will be by default Bold. On clicking other option, it should lose its style class and added to the other option which user clicked. Please help me out on how to do this. Will provide additional details if required.
Add property called activeId to your data object and update it in the selectCountry method:
data() {
return {
defaultCountry: "CST",
Options: [],
activeId:-1
}
},
methods:{
selectCountry(item){
...
this.activeId=item.id;
}
}
in the template add the class binding :
<li class="country-menu-item" :class="{'active':item.id===activeId}" v-for="item in Options"
I am trying to use both regular class attribute and class conditional attribute in an html element below:
<ul *ngIf="showDropdown">
<li class="active" [class.active]="sIndex === x" (click)="dropdownSelect($event.target.value, x)" value="18203">All Groceries</li>
<li [class.active]="sIndex === x" (click)="dropdownSelect($event.target.value, x)" *ngFor='let i of lists; let x = index' value="{{i.id}}">{{i.name}}</li>
</ul>
I have the first li I want to be active but have click attribute which toggles click. Any ideas?
You can use
[ngClass]={"active": sIndex === x}
But in your code you already have the class "active" by default, so nothing will change, always going to have the active class.
explain more, what you want to do.
You're example is looking weird ,
the first li is always active no matter what will happen , and both of li have the same condition that makes them active .
Try this
<ul *ngIf="showDropdown">
<li [class.active]="sIndex === x" (click)="dropdownSelect($event.target.value, x)" value="18203">All Groceries</li>
<li [class.active]="sIndex !== x" (click)="dropdownSelect($event.target.value, x)" *ngFor='let i of lists; let x = index' value="{{i.id}}">{{i.name}}</li>
</ul>
This is the right way to add a class in case its true
[class.active]="sIndex === x"
I figured the answer out. So if you want to have a conditional where active class changes when you click, but want an active class on any element first you do the following:
[ngClass]="{'active': sIndex === x || first}" (click)="dropdownSelect($event.target.value, x)"
add a conditional parameter with your toggle active class on click.
constructor(private api: API, private http: Http) {
this.first = true;
}
you set first to true in in your constructor. then when someone clicks, you put it into function and set it to false;
dropdownSelect(v, x: number) {
this.filter = v;
this.sIndex = x;
this.showDropdown = !this.showDropdown;
this.first = false;
}
I want to add background color to the li element when clicked but when I clicked another li element the previous li element background color remains unchanged.
component.html
<div class="col-md-3 categories">
<h3>News By Type</h3>
<ul>
<li class="cat" id="cat_{{i}}" *ngFor="let category of categories; let i = index" (click)="sortNewsItems($event,category,i)"><img src="../assets/images/news.jpg" width="70"><h4>{{category}}</h4></li>
</ul>
</div>
component.ts
sortNewsItems(event,cat,index) {
event.target.classList.add('cat_active');
}
You should use srcElement of the $event
sortNewsItems(event,cat,index) {
event.srcElement.classList.add('cat_active');
}
Read this answer and use its demo
I know this is an old post but just in case. when there are several classes already on the element you might just want to add or remove an extra class you can do this:
On the element:
<div #element </div>
On the component.ts
#ViewChild('element') element: ElementRef;
then you can just add classes or remove them by
this.element.nativeElement.classList.add("newclass");
this.element.nativeElement.classList.remove("newclass");
Remove 'cat_active' class from all the sibling elements before adding a new 'cat_active' class to the selected element.
component.html
<li #li class="cat" *ngFor="let category of categories;" (click)="sortNewsItems($event)">
component.ts
#ViewChildren('li') livs: QueryList<any>;
constructor(private elementRef: ElementRef) { }
sortNewsItems(event) {
this.livs.forEach(liv => liv.nativeElement.children[0].classList = []);
event.target.classList.add('cat_active');
}
I hope it might helps.
Use ngStyle instead of direct class binding in html element.
component.html
<div class="col-md-3 categories">
<h3>News By Type</h3>
<ul>
<li [ngStyle]="setListItemStyle(category)" class="cat" id="cat_{{i}}" *ngFor="let category of categories; let i = index" (click)="sortNewsItems($event,category,i)"><img src="../assets/images/news.jpg" width="70"><h4>{{category.label}}</h4></li>
</ul>
</div>
component.ts
activeListItem: any = null;
categories: any[] = [{ id: 1, label: 'Test label 1' }, { id: 2, label: 'Test label 2' }];
sortNewsItems(event, category, i) {
event.stopPropagation();
this.activeListItem = category;
}
setListItemStyle(category) {
return { 'background-color': this.activeListItem && this.activeListItem.id == category.id ? '#fff000' : null };
}
I just taken a variable and set category name to it when clicked on category li and add active class based on the below condition. finally I set it like what i want. Thank you everyone for the well support.
component.html
<li class="cat" *ngFor="let category of categories; let i = index" (click)="sortNewsItems(category,i)" [ngClass]="{'cat_active':toggleClass === category}"><img src="../assets/images/news.jpg" width="70"><h4>{{category}}</h4></li>
component.ts
toggleClass:string;
sortNewsItems(cat,index) {
this.toggleClass = cat;
}
I read that using srcElement is not a "so good" practice. Better to use renderer2.
<any-element [ngClass]="{selected: isSelected}">
...
</any-element>
OR
<any-element [ngClass]="{selected: isSelected, disabled: isDisabled}">
...
</any-element>
document.querySelector(".menu-open-btn a").onclick = function addNewClass() {
document.querySelector(".mobile-header").classList.add("newClass");
}
I want to add a class to an element if the title of the page includes "Home".
Currently, I use this:
<li data-bind="css: { 'active': function(){return document.title.indexOf('Home') > -1;}}">
However this does not work, this function does not get executed...
How do I make this work?
Knockout wraps the value in a computed function in a way that resembles this:
Input: "yourClassName": whateverYouPutIn
Output: "yourClassName": ko.computed(function() { return whateverYouPutIn; })
In your case, you put in a function, which will result in a "truethy" value setting the active class. You can fix this by:
Option 1 (quick): Don't wrap it in a function
<li data-bind="css: {
'active': document.title.indexOf('Home') > -1
}"></li>
Option 2 (not recommended): Fix the typo (funciton) and call the function
<li data-bind="css: {
'active': (function() {
return document.title.indexOf('Home') > -1;
}())
}"></li>
Option 3: Add these kinds of properties to your viewmodel
var vm = {
// set when VM is initialized
isActive: document.title.indexOf("Home"),
// if you want to check the title during data-binding
isActiveDuringBind: function() {
return document.title.indexOf("Home");
}
}
With either
<li data-bind="css: {'active': isActive }"></li>
or
<li data-bind="css: {'active': isActiveDuringBind() }"></li>
Note that using the DOM api outside of custom bindings is considered "bad practice"... But in this case I guess you can get away with it...
Note that because there are no observable values being used, your class will not toggle when you change document.title.
I am trying to add the class by ng-class in my app.
I have something like
html
<li ng-repeat="item in items"
ng-click="getItem(item)"
ng-class="{shine : item.isPick}" // shine class will make the font color change to red
>{{item.name}}
</li>
In my controller
$scope.getItem = function(item) {
$scope.items.forEach(function(item){
item.isPick = false; // remove all the items that have shine class
})
item.isPick = true; // adding the shine class back
}
Basically I want to remove every other 'shine' class except the selected item when user clicks it. My codes above work but I am thinking there is a better way to do it instead of looping all the items. Can someone help me about it? Thanks a lot!
Use the $index in the repeater, and add the class when that index is selected:
<li ng-repeat="item in items"
ng-click="getItem($index)"
ng-class="{shine : activeIndex == $index}"
>{{item.name}}
</li>
$scope.getItem = function(index) {
$scope.activeIndex = index;
}