Add 'check' class to previous item after clicking a button - javascript

I'm trying to add a class unlocked on previous item when I click button and my current moves to next item, but I can't figure out how. Current functionality is working fine but I want to add unlocked class. Any help would be great.
<ul>
<li class="locked" *ngFor="let subLecture of lectureList; let j = index"
[ngClass]="{ 'current': lectureIndex == j}"
(click)="lectureItemClick(j)">
<a>{{subLecture}}</a>
</li>
</ul>
<button (click)="nextLectureSecond()">Next</button>
Here's an attached demo: https://stackblitz.com/edit/angular-ivy-cdiev5

You can add another condition as well in the [ngClass], something like 'unlocked': lectureIndex > j if you wish to apply the class to all the previous items.
See if this helps:
<ul>
<li class="locked" *ngFor="let subLecture of lectureList; let j = index"
[ngClass]="{ 'current': lectureIndex == j, 'unlocked': lectureIndex > j}"
(click)="lectureItemClick(j)">
<a>{{subLecture}}</a>
</li>
</ul>
Similarly, you can change the logic to suit your scenario.
Stackblitz: https://stackblitz.com/edit/angular-ivy-62422113

Although It's not recommended to use the document keyword if you are using server-side rendering, you can use another workaround as well, you can follow the below way as well.
<li class="locked" *ngFor="let subLecture of lectureList; let j = index" [id]="j">
....
</li>
nextLectureSecond() {
....
let ele = document.getElementById(this.lectureIndex.toString());
(<HTMLParagraphElement>ele).classList.add("unlocked");
const a = this.lectureIndex++;
....
}
Working Example

Just the previous item?
Change your ng-class declaration like this :
[ngClass]="{ 'current': lectureIndex == j, 'unlocked' : (lectureIndex!=0 && lectureIndex - 1 == j )}"
Se here

Related

Angular - How to include button event?

Is there a way to include button in this code which will with click make the same change to an array the same way [ngStyle] does in the following part of the code?
app.component.html
<div class="styling">
<ul>
<li *ngFor = "let a of arr"
[ngStyle]="changeFont()">
{{a}}
</li>
</ul>
</div>
app.component.ts
arr=['car','house','beach','microphone'];
changeFont(){
return {'font-size.px':15}
}
In Angular you has variables in .ts, and use this variables in the .html.
An example
style:any=null //declare a variable
toogleStyle() //A function that change the variable
{
if (!this.style)
this.style={'font-size':'15px';color:'red'}
else
this.style=null
}
You can use
<div (click)="toogleStyle()" [ngStyle]="style">click me!</div>
And see how change the style
As you has "severals" <li> you need severals variables if you want severals<li> can be "selected" at time or an unique variable if only one <li> can be selected at time.
The "severals variables" are an Array, so to change one element of
the array you need pass the "index" of the array
styles:any[]=[]
toogleStyle(index:number) //A function that change the variable
{
if (!this.styles[index])
this.styles[index]={'font-size':'15px';color:'red'}
else
this.styles[index]=null
}
<ul>
<!--see using let i=index, i becomes value 0,1,2,3...->
<li *ngFor = "let a of arr;let i=index"
<!--see you pass the "index" to the function-->
[ngStyle]="styles[i]" (click)="toogleStyle(i)">
{{a}}
</li>
</ul>
The unique variable is a number that is the "index" selected. For no
selected index, the variable becomes -1 (Remember that 0 is the fisrt
element of the array)
selectedIndex:number=-1
toogleStyle(index:number) //A function that change the variable
{
if (this.selectedIndex==index) //if you click on selected <li>
this.selectedIndex=-1;
else
this.selectedIndex=index;
}
<ul>
<li *ngFor = "let a of arr;let i=index"
<!--you use the conditional operator (condition)?
value if condition is true:
value if condition is false
-->
[ngStyle]="i==selectedIndex?
{'font-size':'15px';color:'red'}:
null"
(click)="toogleStyle(i)">
{{a}}
</li>
</ul>

Angular - Create component tree menu

I am creating a tree menu, visually it looks like this:
The tree has been created based on an array of objects obtained from a service, extracted from a date property.
Now, I have to get the tree menu to allow displaying and collapsing the: years, months and complete dates, in the style of this component:
https://angular2-tree.readme.io/
Ideally, I'd do this with typescript, but if it's hard for me, I'd try using an external component.
This is the html code:
<ul>
<li *ngFor="let y of tree | keyvalue">{{y.key}}
<ul>
<li *ngFor="let m of tree[y.key] | keyvalue">{{m.key}}
<ul>
<li *ngFor="let d of tree[y.key][m.key] | keyvalue">{{d.key}}
<ul>
<li *ngFor="let h of tree[y.key][m.key][d.key]"><a [ngClass]="{'hourSelected': (idSchedule === h.id || lastId === h.id),'hourUnSelected': idSchedule !== h.id}" (click)="loadMacroProcesses(h.id)">{{h.hour}}</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
This would be the solution, now I will refine it:
<ul>
<li id="year" *ngFor="let y of tree | keyvalue; let i=index" (click)="listClick($event, i)">{{y.key}}
<ul [hidden]="indexExpandedYear!=i?true:null">
<li id="month" *ngFor="let m of tree[y.key] | keyvalue; let j=index" (click)="listClick($event, j)">{{m.key}}
<ul [hidden]="indexExpandedMonth!=j?true:null">
<li id="day" *ngFor="let d of tree[y.key][m.key] | keyvalue; let k=index" (click)="listClick($event, k)">{{d.key}}
<ul [hidden]="indexExpandedDay!=k?true:null">
<li *ngFor="let h of tree[y.key][m.key][d.key]"><a [ngClass]="{'hourSelected': (idSchedule === h.id || lastId === h.id),'hourUnSelected': idSchedule !== h.id && lastId !== h.id}" (click)="loadMacroProcesses(h.id)">{{h.hour}}</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
This is the typescript method:
listClick(event, i) {
switch (event.srcElement.id) {
case "year":
this.indexExpandedYear = this.indexExpandedYear==i?-1:i;
event.stopPropagation();
break;
case "month":
this.indexExpandedMonth = this.indexExpandedMonth==i?-1:i;
event.stopPropagation();
break;
case "day":
this.indexExpandedDay = this.indexExpandedDay==i?-1:i;
event.stopPropagation();
break;
default:
break;
}
}
Can you recommend me a good one external component? Thanks.
NOTE: I am working with version 11 of Angular
NOTE: If you deploy one year, the rest of the years should be collpased back.
NOTE: Angular material is not valid for me
You could add a parameter for visibility and click event to the parent ul. How it would work is that they would have a boolean value on them for visibility that would change when you click the top ul element. You would have a method that would just switch between true/false and display if true hidden if false. Click event should be on the top li element and visibility on its child.
You should checkout the tree component provided by primeng. It has its own data format and can do your own customisation on top it.

How to get 1st true value for *ngIf inside *ngFor

I have an array of items that need to be displayed based on roles. I need the first value which will fulfil the ngIf condition.
I am adding my code below:
My Array(kind of how it will originally look):
parentTabList = [
{
name: 'abc',
label: 'abc',
icon : 'question_answer',
role : ['vend_perm','vend_temp','vend_subs']
},
{
name: 'xyz',
label: 'xyz',
icon : 'question_answer',
role : ['vend_perm','vend_subs']
}
]
My Html: -
<ng-container *ngFor="let form of parentTabList let i = index">
<li *ngIf="form.role.includes(userRole)">
<a (click)="methodName(form)">
{{form.label}}
</a>
</li>
</ng-container>
UserRole is a string value that I get when a user logs-in.
I need to add a ngClass to the anchor tag if it is the first anchor to be displayed.
(I am a noob at StackOverflow, please let me know if any more explanation is required).
You can identify first element of the array with index.
But as per my understanding you need filter this array with roles and then apply ngClass to first element from filtered list.
So add method to return filtered array with respect to roles
In Template:
filterParentTabList(parentList: any) {
return parentList.filter(form => form.role.includes(this.userRole));
}
In View:
<ng-container *ngFor="let form of filterParentTabList(parentTabList); let i = index">
<li>
<a [ngClass]="{ 'addYourClaaName': i === 0 }" (click)="methodName(form)">
{{form.label}}
</a>
</li>
</ng-container>
Happy Coding.. :)
You can write like this. In this code, f represents the first position of your array.
<ng-container *ngFor="let form of parentTabList; let i = index; let f = first">
<li *ngIf="f">
<a (click)="methodName(f)">
`{{f.label}}`
</a>
</li>
</ng-container>
If you want other position of your array, you can write like you mentioned above.
You can define a getter that will get you the index. This can then be used in the html
get firstIndex() {
return this.parentTabList.indexOf(this.parentTabList.find(({role}) =>
role.includes(this.userRole)))
}
Now in your html
<ng-container *ngFor="let form of parentTabList let i = index">
<li *ngIf="form.role.includes(userRole)">
<a [ngClass]="{redText: firstIndex === i}" (click)="methodName(form)">
{{form.label}}
</a>
</li>
</ng-container>
See Stackblitz Demo Here

ng-checked not working for multiple condition expression in angular js template

I want to check the Users check box on selection of category. But when there is no key for Category in usr_cat array previously checked check boxes not unchecked. I want to uncheck all the users when Manager is selected in the category.
Category = [{cid:'1',name:'Head'},cid:'2',name:'Manager'}]
users = [0:{'id':10,name:'AAAAA'},{'id':12,name:'BBBBB'},{'id':13,name:'CCCCC'},{'id':14,name:'DDDDDDDD'}]
usr_cat = ['1':[10,14]]
Category List
<ul class="list-unstyled cat-lst">
<li ng-repeat = "cat in categery" ng-click ="selectcategry(cat.cid)>{{cat.name}} </li>
<ul>
User List
<ul class="list-unstyled usr-lst">
<li ng-repeat = "usr in users">
<span class=" checkbox ">
<input class="optionChechk " id="user_{{usr.id}}" type="checkbox" ng-checked = "{{usr_cat[sele_cid] != 'null' && usr_cat[sele_cid] != 'undefined' && usr_cat[sele_cid] != '' && (usr_cat[sele_cid].indexOf(usr.id) != -1)}}" ng-value="{{usr.id}}" >
<label for="user_{{usr.id}}" txt = "{{usr_cat[sele_cid]}}">{{usr.name}}</label>
</span>
<li>
</ul>
JS
$scope.selectcategry = function(cid){
$sele_cid = cid;
}
Hi the code contains many error
Angular braces are used inside ng-attributes.
improper closer of quotes"".
Improper naming standards camel-casing is the format.
Category is the variable you mentioned spelling categery is used
everywhere.
<ul class="">
<li ng-repeat = "cat in categery"
ng-click ="selectcategry(cat.cid)">{{cat.name}}</li>
</ul>
Array responses are seem to inValid,suggested bellow,scope is missing in sele_cid
$scope.categery =[{"cid":'1',"name":'Head'},{"cid":'2',"name":'Manager'}];
$scope.users = [{'id':10,"name":'AAAAA'},{'id':12,"name":'BBBBB'}, {'id':13,"name":'CCCCC'},{'id':14,"name":'DDDDDDDD'}];
$scope.usr_cat = [10,14];
$scope.selectcategry = function(cid){
$scope.sele_cid = cid;
}
please work on this

How can I have several statements inside a structural directive on Angular2

I'm new to Angular 2 and haven't worked front end before. So I'm not sure how to write a template structural directives. I need to translate this from ejs/angular 1 to Angular 2
for (var i = 0; i < n; i++) {
<% var classes = item.columns[i].fields.skin.indexOf("sign-in") > -1 ? "sign-in" : "" %>
<div class="dropdown menu-standout desktop <%= classes %>">
<a><%= item.columns[i].fields.title %></a>
</div>
}
My best guess was this, but I'm sure I can't have curly brackets twice inside ngFor. Any help?
<li *ngFor="let column of item.columns">
{{var classes = column.fields.skin.indexOf("sign-in") > -1 ? "sign-in":""}}
<div class="dropdown menu-standout desktop" {{ classes }}>
<a>{{column.fields.title}}</a>
</div>
</li>
You can not have binding assignment in template interpolation directive.
So, it should be like this
{{column.fields.skin.indexOf("sign-in") > -1 ? "sign-in":""}}
You can not declared variable inside interpolation directive
Remove the var classes = part from template otherwise it will template parse error.
you want to add a class dynamically, so try this :
<li *ngFor="let column of item.columns">
<div [class.active] = "isActive = 'column.fields.skin.indexOf("sign-in") > -1 ? "sign-in":"" ' " class="dropdown menu-standout desktop">
<a>{{column.fields.title}}</a>
</div>
</li>
it is not good practice to have js code in your view.
in your component
export class MyComponent {
isActive: boolean = false;
}
I fixed the syntax by writing an extra function
<li *ngFor="let column of item[0].fields.columns">
<div class="dropdown menu-standout desktop {{ checkIndex(column) }}" >
<a>{{column.fields.title}}</a>
</div>
</li>
export class PageDropdownComponent {
constructor() {}
checkIndex(classes:any) {
return classes.fields.skin.indexOf("sign-in") > -1 ? "sign-in" : "";
}
Thanks everyone else for the help, it was useful for understanding the syntax

Categories

Resources