How i Do Click to Change CSS in Angular - html

I have a button/img in LI. I want to when clicked change css and text-decoration underline.
Ts file :
onSelect(i: number) {
var element = document.getElementsByClassName('brand')[i];
const elementClass = element.className;
if (elementClass != 'btn brand selected') {
this.renderer.addClass(element,'selected');
}
else{
this.renderer.removeClass(element,'selected');
}
}
HTML file :
<li class="nav-item" *ngFor="let brand of brands let i = index">
<button class="btn brand" id="brand" type="button" data-toggle="showCategory" aria-controls="tabOne"
data-target="#tabOne" href="#merk1" (click)="getCategories(brand.id); onSelect(i);">
<img [src]="brand.imageLink" width="100" height="40" [alt]="brand.name" role="button">
</button>
</li>

The simplest solution could be using [ngClass] directive with some logic rather than getting the DOM element and manipulating it.
// declare a variable to which assign the selected brand index
selectedBrand: number;
In template assign the current selected index
<li class="nav-item" *ngFor="let brand of brands let i = index">
<button class="btn brand" (click)="getCategories(brand.id); selectedBrand=i"> <=== NOTE this
<img [src]="brand.imageLink" width="100" height="40" [ngClass]="{'selected': selectedBrand === i}"> <=== You can assign any class if the current index and selected index is matched
</button>
</li>
Hope this works with you

Related

How to assign independent of [(ngModel)] in *ngFor list and select HTML tag

I have a problem with [(ngModel)], it syncs all my select to variable
my variable is selectStations = [];
So, when I select an option inside, it will render all select to select the same one and assign to all slot in a variable (see the picture below, just look at it override all slot that is available)
Typesript:
stations: StationModel[] = [];
selectStations = [];
addSlotSelectStation(){
this.view.loading = true;
this.selectStations.push(null);
console.log(this.selectStations);
this.view.loading = false;
}
addSelectStation(index: number, stationId: string) {
console.log(index);
this.selectStations[index] = stationId;
}
deleteSelectStation(index: number): void{
this.selectStations.splice(index, 1);
console.log('delete index', index);
}
HTML:
<button class="btn btn-primary" (click)="addSlotSelectStation()">
add slot
</button>
<!-- List Group All -->
<ul class="list-group overflow-auto">
<!-- Loop List All Select Station -->
<li
*ngFor="let selectStation of selectStations; let index = index"
class="list-group-item"
>
<div class="form-inline">
<!-- Order Number -->
<span class="mr-3">{{ index + 1 }}</span>
<!-- Selection Dropdown -->
<select
#selectnow
class="form-control bg-light col mr-3"
name="selectStation[{{index}}]"
formControlName="selectStation"
size=1
[(ngModel)]="selectStations[index]"
(change)="addSelectStation(index, selectnow.value)"
>
<option selected value="">choose station...</option>
<option
*ngFor="let station of stations"
[value]="station.id"
>
{{ station.name }}
</option>
</select>
<!-- For test debug reasons -->
<div>{{ selectStations[index] }}</div>
<div>{{ index }}</div>
<!-- Delete Select Station -->
<button
class="btn btn-outline-info"
(click)="deleteSelectStation(index)"
>
X
</button>
</div>
</li>
</ul>
Result:
So That's the problem, I want it just select only one, and assign value only one each selector, not override another selector value.
[Solved] I change it from [(ngModel)] to use FormArray. That's very useful when it come across iterating in the list of input/dropdown and etc.
This Link is super useful, Check it out! :)
Angular Reactive Forms: The Ultimate Guide to FormArray

How to attach a checkbox to each of the items of a list with ngModel in Angular?

I want to have a checkbox attached to each text of my list.
Like this:
Text1 [Checkbox1]
Text2 [Checkbox2]
Text3 [Checkbox3]
Text4 [Checkbox4]
The list is dynamic therefore checkboxes should also appear dynamically next to each item of the list.
I should be able to set the default value of each checkbox in the beginning and also gather their values when user clicks on them.
I have tried this:
<div *ngIf = "blogs.length > 0">
<ul>
<li *ngFor = "let blog of blogs"
(click) = "onSelect(blog)"
[class.selected] = "blog === clickedOnThisBlog">
<a *ngIf = "blog.show === true" routerLink = "/editor/{{blog.id}}">
{{blog.title}}
creationDate: {{blog.creationDate}}
modificationDate: {{blog.modificationDate}}
</a>
<a *ngIf = "blog.show === true">
<input type = "checkbox"
[ngModel] = "checkboxChecked"
#checkbox_l = "ngModel"
value = "blog"
(click) = "onCheckboxClicked( checkbox_l, value )" >
</a>
</li>
</ul>
</div>
The first half of this code shows the list of text.
In second half I have attempted to attach the checkboxes with each of the text.
I don't know how to link the list of checkboxes back to the .ts file so that I can control them at one place there.
This is a template driven code. ngModel has to be used.
What's the way out?
I defined an array in the corresponding .ts file as follows:
checkboxes: CheckboxStructure[] = []
CheckboxStructure is defined as follows:
export interface CheckboxStructure
{
id: number
value: boolean
}
I wrote let i = index in *ngFor and attached my checkboxes array's particular field to [ngModel] like this: [ngModel] = "checkboxes[i].value"
<div *ngIf = "blogs.length > 0">
<ul>
<li *ngFor = "let blog of blogs; let i = index;" >
<a *ngIf = "blog.show === true" routerLink = "/editor/{{blog.id}}">
{{blog.title}}
creationDate: {{blog.creationDate}}
modificationDate: {{blog.modificationDate}}
</a>
<a *ngIf = "blog.show === true">
<input type = "checkbox"
[ngModel] = "checkboxes[i].value">
</a>
</li>
</ul>
</div>
Credit: *ngFor how to bind each item in array to ngModel using index

How to change text and button image (or button) when I click

I am working with angular. When I click a button, I get a dropdown with some choices. How can I change the button image or button and text when I click on it? The goal is for it to return to its original state when it is clicked again.
I leave the image here to understand better.
The button in my case will be an image.
What I want is this: I click the button and open the dropdown, in that dropdown, when I click Start, I want the image of the button to be changed (or the button) and Start to be Pause. If you do the same again, the opposite happens ... that is, if you have Pause, pressing it changes the button and Pause becomes Start.
It is possible? Can anyone help me?
Example, my code
Codepen
HTML
<div class="dropdown">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
<img src="">
</button>
<div class="dropdown-menu">
<a class="dropdown-item">Start</a>
<a class="dropdown-item">Add new</a>
</div>
</div>
I am working with angular, if anyone can help me get the solution using their resources, I really appreciate
Use a variable to store the current state and toggle view using it's value.
app.component.ts :
currentState : string = 'pause'
app.component.html :
<div class="dropdown">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
<!-- Image is to be shown by default -->
<img src="1.png" *ngIf="currentState=='pause'"">
<!-- Image is to be shown on clicking start -->
<img src="2.png" *ngIf="currentState=='start'"">
</button>
<div class="dropdown-menu">
<a class="dropdown-item" *ngIf="currentState=='pause'" (click)="currentState='start'">Start</a>
<a class="dropdown-item" *ngIf="currentState=='start'" (click)="currentState='pause'">Pause</a>
</div>
</div>
add a function to onChange and do it there,
<div class="dropdown">
<button (change)="changeImg()" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
<img src="{{imgSrc}}">
</button>
<div class="dropdown-menu">
<a class="dropdown-item" *ngIf="isStarted">Start</a>
<a class="dropdown-item" *ngIf="!isStarted">Pause</a>
<a class="dropdown-item">Add new</a>
</div>
</div>
in ts,
isStarted:boolean = false; // default to pause
imgSrc:any;
changeImg(){
// We can even write the simplest code instead the below line.
// isStarted = false ? true : false;
isStarted = !isStarted;
imgSrc = isStarted ? startImageSrc : pauseImageSrc;
}
hope this works, did not test :)

angular7 building an navroute component but don't know what to do now

there is no issue with this code
to be more specific
can I create value's within my angular HTML or not?
I couldn't find anything about it so I think not and what do I do now if I want to create an automated menu.
i am using angular materials in this
I need to create a nav bar but I created it in angular HTML with some stuff in TS to create the data it needs to be automatic
so I need to loop this bottom part of my code with any value but I don't know how to start
<!-- need to loop this block of code whenever there is any new item with children -->
<div *ngFor="let childss of childs.children">
<div *ngIf="childss.children != null">
</div>
<a routerLink="/{{navRoute.path}}/{{childs.path}}/{{childss.path}}"><button mat-menu-item>{{childss.path}}</button></a>
</div>
</mat-menu>
</div>
<ng-template #elsesBlock>
<a routerLink="/{{navRoute.path}}/{{childs.path}}"><button mat-menu-item>{{childs.path}}</button></a>
</ng-template>
<!-- till here but have no idee how to do this effectively -->
childs is an item of an array
but it needs custom input data for the loop to function correctly but I have no idea how to do it if
<div class="nav_items" *ngFor="let navRoute of navRoutes">
<div *ngIf="navRoute.children != null; else elseBlock">
<div *ngIf="navRoute.children != null">
<a routerLink="/{{navRoute.path}}">
<button mat-button [matMenuTriggerFor]="menu">{{navRoute.path}}</button>
</a>
<mat-menu #menu="matMenu">
<div *ngFor="let childs of navRoute.children">
<div *ngIf="childs.children != null; else elsesBlock">
<a routerLink="/{{navRoute.path}}/{{childs.path}}">
<button mat-menu-item [matMenuTriggerFor]="child">{{childs.path}}</button>
</a>
<mat-menu #child="matMenu">
<!-- need to loop this blok of code when ever there is anny new item with children -->
<div *ngFor="let childss of childs.children">
<div *ngIf="childss.children != null">
</div>
<a routerLink="/{{navRoute.path}}/{{childs.path}}/{{childss.path}}"><button mat-menu-item>{{childss.path}}</button></a>
</div>
</mat-menu>
</div>
<ng-template #elsesBlock>
<a routerLink="/{{navRoute.path}}/{{childs.path}}"><button mat-menu-item>{{childs.path}}</button></a>
</ng-template>
<!-- till here but have no idee how to do this effectively -->
</div>
</mat-menu>
</div>
</div>
<ng-template #elseBlock>
<a routerLink="/{{navRoute.path}}">
<button mat-button>{{navRoute.path}}</button>
</a>
</ng-template>
</div>
this is my entire HTML
nav route is an array from my routes
I tried HTML link but that doesn't work with angular items
Try this syntax for your routerLink:
[routerLink]="['/' + navRoute.path + '/' + childs.path]"

Line break in ngFor loop

I have an ngFor that creates several PrimeNG buttons. Right now, the buttons appear directly after each other on the same row - I would like each button to display on its on line vertically. How do you go about doing that? Here is my ngFor code:
<button pButton type="button"
*ngFor="let atrConfig of atrConfigs; let i = index"
(click)="selectConfiguration(atrConfig)" label = "">
Name: {{atrConfig.name}} <br />
</button>
You should use a ng-container tag which groups elements but doesn't get rendered in the DOM tree as a node.
<ng-container *ngFor="let atrConfig of atrConfigs; let i = index" >
<button pButton type="button"
(click)="selectConfiguration(atrConfig)" label = ""> Name: {{atrConfig.name}}
</button>
<br />
</ng-container>
In this example, it may be just as simple to use CSS, but ng-container can be very useful if you don't want a surrounding div e.g. populating a table
Just add a css class with display: block to your button.
Or add it inline like the next example:
<button pButton type="button" style="display: block;"
*ngFor="let atrConfig of atrConfigs; let i = index"
(click)="selectConfiguration(atrConfig)" label = "">
Name: {{atrConfig.name}} <br />
</button>
I don't have idea if the pButton directive adds styles to the button that can override the display value.