handle Onclick event from Vue to Vuex - html

I'm switching from vue to vuex and I'm having trouble implementing an onclick event. I'm using bootstrap collapse to create 3 div. Each div has a button to show the collapsible elements inside. With vue I'm taking the data from an api request. I want every single button to open its parent div. Currently every button open all the three divs. When using vue I simply wrote this:
methods:{
//set expand to true foreach player card,
//set open to true foreach plus button
playerCardCollapse(index) {
this.teams = this.teams.map((item, i) => {
item.expanded = !item.expanded
item.open = !item.open
if (i !== index) {
item.expanded = false
item.open = false
}
return item
})
},
},
This is my template:
<!-- Container Card -->
<div v-for="(team, i) in teams" :key="i" class="col-6">
<div class="row mb-2 team-default align-items-center" style="height:106px;">
<div class="col-2 section">
<img class="rounded-circle" :src="team.team_img" style="border:2px solid #fff;box-shadow: 0 2px 31px 0 rgba(0, 0, 0, 0.23);">
</div>
<div class="col section team end">
<p class="intestazione">Team Name:</p>
<p class="result">{{team.team_name}}</p>
</div>
<div class="col-2 section end">
<button type="button" class="btnProfile" data-bs-toggle="collapse" data-bs-target="#profile-row" :aria-expanded="team.expanded" aria-controls="profile-row" #click.prevent="playerCardCollapse(i)">
<div class="plus-icon" :class="{open: team.open}"></div>
</button>
</div>
</div>
<!-- Collapsed -->
<div v-if="team.player.length>0">
<div class="collapse show" :class="{show: team.expanded}">
<div v-for="(p, j) in team.player" :key="j" class="row team-default mt-2 mb-3" id="profile-row">
<div class="col-2 section">
<div class="player-img-container">
<img class="rounded-circle player-img" :src="p.profilePic">
<img class="rounded-circle flag-img" src="https://picsum.photos/31/31">
</div>
</div>
<div class="col section team end">
<p class="intestazione">Team {{p.role}}</p>
<p class="result">{{p.name}}</p>
</div>
<div class="col-4 section end">
<button class="btnProfile-cta">Visualizza Profilo</button>
</div>
</div>
</div>
</div>
</div>
But with vuex I don't know how to implement this playerCardCollapse().
Hope someone could help (I don't know if you need more code snippets)

Related

Change column sizes by clicking in angular

i have this page that has two buttons divided By two clo-md-6 :
i want when i click in the button the first button become col-md-9 and the other col-md-3 and the same for the inverse
i don t know how to do it in angular
This is my HTML :
<div class="container-fluid">
<div class="row">
<!-- $("#btn1").parentElement.parentElement.className= "col-3"-->
<!--------------------THE FIRST BUTTON----------------------------->
<div class="col-xl-6" [class.col-xl-9]="isclicked">
<div class="card">
<button type="button" id="btn1" class="btn btn-primary" (click)="AfficherRecherche()">Agent professionnelle</button>
<div class="card-body" *ngIf="isclicked">
<h4 class="header-title mt-0 mb-4">Agent Professionnelle</h4>
<aw-wizard>
<aw-wizard-step class="sw-main sw-theme-default">
<form [formGroup]="searchForm">
<div class="row">
<div class="col-12">
<div class="form-group row mb-3">
<input type="text" class="form-control" (keyup)="searchTerm.next($event)" formControlName="search" placeholder="Rechercher ..." (input)="search()" [(ngModel)]="searchText" />
<div *ngIf="loading">
<p class="search-message">Searching</p>
<div class="lds-ellipsis">
<!-- -------------------------------THE SEOND BUTTON------------------------------------------------------------------ -->
<div class="col-xl-6" [class.col-xl-3]="isclicked">
<div class="card">
<div class="btn-group">
<button id="btn2" type="button" class="btn btn-primary" (click)="AfficherAgentpar()">Agent Partculier</button>
</div>
this is my component :
AfficherRecherche() {
this.isclicked = !this.isclicked;
}
AfficherAgentpar() {
this.agentparclick = !this.agentparclick;
}
You should trigger classes on click. So for example:
In your TS file declare a variable with a boolean:
public resize: boolean;
In your HTML you have 2 divs and a button:
<div class="clo-md-6" [class.col-md-9]="resize"></div>
<div class="clo-md-6" [class.col-md-3]="resize"></div>
<button (click)="resize != resize">Trigger me</button>
What happens is the following: When the button gets clicked it changes the value of our resize boolean. Since this is false by default, it'll trigger to true. When resize is true, the first div will be assigned the col-md-9 class, and the second div will be assigned the col-md-3 class. If you click the button again, the divs will go back to being 50/50.

How do i incorporate multiple divs inside a bootstrap modal-body?

I'm currently trying to make a single modal with multiple <div> tags inside the modal-body div.
Example based on what i am doing:
HTML:
<div class="modal-body">
<div id="main"> //Main Div or Menu
<div class="card-deck">
<div class="card">
<a href="#" id="gen"> //Gen Trigger
<div class="card-body">
... //Content
</div>
</a>
</div>
<div class="card">
<a href="#" id="light"> //Light Trigger
<div class="card-body">
...
</div>
</a>
</div>
</div>
<div id="gen-content" style="display: none"> //Modal That Gets Triggered.
<div class="card-body p-0 m-0">
<div class="text-right">
<a class="btn btn-danger btn-back" href="#">Back</a>
</div>
Content
</div>
</div>
<div id="light-content" style="display: none"> //Another Modal That Gets Triggered.
<div class="card-body p-0 m-0">
<div class="text-right">
<a class="btn btn-danger btn-back" href="#">Back</a>
</div>
Content
</div>
</div>
</div>
jQuery:
$("#gen").on('click', function() {
$("#main").hide();
$("#gen-content").show();
});
$("#light").on('click', function() {
$("#main").hide();
$("#light-content").show();
});
$(".btn-back").on('click', function(){
$("#gen-content").hide();
$("#main").show();
});
Above code works fine, but clicking the back button scrolls the page way up to the top. And closing it resets it to the original <section>. Is there anything more i can improve with this code? I also think the way i code the content triggers is a bit long.
Found a fix by browsing on the jQuery forums. It read:
use return false; at end of click handler to avoid browser default event on a link. If there is no match to element in href, page will jump to top by default.
I fixed by using:
$("#gen").on('click', function() {
$("#main").hide();
$("#gen-content").show();
return false;
});
$(".btn-back").on('click', function(){
$("#gen-content").hide();
$("#main").show();
return false;
});

Multiple lists with drag & drop within group

I have two divs in a parent component. And there are cards (components rendered in divs) in each of the above two divs. Each card has got a list of employees (also divs) from which I want to drag any across other cards within their own parent div.
Below image shows how my page look like:
I want the page to be able to drag employees within Pickup or Drop. For eg: move Employee1 from {Place1 To Place2} to {Place3 To Place2} I have used cdkDropList/cdkDrag, however I could not drag anything at all.
Below is my html for parent component with the Pickup & Drop divs:
<div class="row">
<div class="col-md-12">
<h5 class="bg-primary text-white">Pickup</h5>
</div>
</div>
<!-- Pickup DIV -->
<div class="row" cdkDropListGroup>
<div class="col col-md-4" *ngFor="let item of pickupCabs" cdkDropList [cdkDropListData]="item.AssignedEmployees"
(cdkDropListDropped)="onDrop($event)">
<app-admin-special-request-allocation-card [allocatedCab]="item"
(childevent)="onSpecialRequestReallocation($event)" cdkDrag>
</app-admin-special-request-allocation-card>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h5 class="bg-primary text-white">Drop</h5>
</div>
</div>
<!-- Drop DIV -->
<div class="row" cdkDropListGroup>
<div class="col col-md-4" *ngFor="let item of dropCabs" cdkDropList [cdkDropListData]="item.AssignedEmployees"
(cdkDropListDropped)="onDrop($event)">
<app-admin-special-request-allocation-card [allocatedCab]="item"
(childevent)="onSpecialRequestReallocation($event)" cdkDrag>
</app-admin-special-request-allocation-card>
</div>
</div>
Below is my html for the individual cards/routes (app-admin-special-request-allocation-card.component.html)
<div class="card bg-light shadow p-3 mb-4 bg-white corners mt-2 mb-2">
<div class="card-body text-center">
<div [class.alert-danger]="!isAllocatedSuccess" [class.alert-success]="isAllocatedSuccess" class="alert"
*ngIf="isAllocated">{{message}}</div>
<div class="row">
<div class="col text-right">
<span><b>{{allocatedCab.AllocationStatusText}}</b></span>
</div>
</div>
<div class="row">
<div class="col-md-3">
<i class='fas fa-{{allocatedCab.CabType|lowercase}}' style='font-size:30px;'></i>
<br>
<b>{{allocatedCab.Occupance}}/{{allocatedCab.Capacity}}</b>
<p><b><span>{{allocatedCab.RouteType}}</span></b></p>
</div>
<div class="row">
<p><b><span>{{allocatedCab.PickupPoint}} To {{allocatedCab.DropPoint}}</span></b></p>
</div>
<div class="row">
<p style="text-align: left"><b><span>{{allocatedCab.VendorName}} -
{{allocatedCab.CabName}} - {{allocatedCab.RegNo}}</span></b></p>
</div>
<!-- employee list -->
<div class="row" *ngFor="let employee of allocatedCab.AssignedEmployees">
<p style="text-align: left"><span class="fa fa-user"></span>
<a href="./admin#" (click)="open(content,allocatedCab,employee)">
{{employee.FirstName}} {{employee.LastName}} -
<small> {{employee.PickupDate | date: "hh:mm a"}} </small>
</a>
<i style="color:red; cursor: pointer;" class="fa fa-remove"
(click)="openConfirmation(content1, employee)"></i></p>
</div>
</div>
<div class="row">
<div class="col-md-6 pt-2 text-left ">
<span>{{allocatedCab.PickupDate | date: "dd/MM/yyyy hh:mm a"}}</span>
</div>
</div>
</div>
</div>
I think there is a mistake in your code. The cdkDropList attribute is placed in the wrong div. And the cdkDrag attribute should be given to the exact div which can be draggable. So only give cdkDropListGroup attribute in parent div and place cdkDropList attribute inside the card component. ie.
You don't need cdkDropList attribute and the following code in that element in your parent div (Pickup and Drop).
Instead, add it in app-admin-special-request-allocation-card.component.html to a new wrapping div over the employee list div.
Add the cdkDrag attribute to exact div in which employee name is rendered.
try the below code.
Parent Component
<div class="row">
<div class="col-md-12">
<h5 class="bg-primary text-white">Pickup</h5>
</div>
</div>
<div class="row" cdkDropListGroup>
<!-- remove the 'cdkDropList' attribute and [cdkDropListData]=" from below div -->
<div class="col col-md-4" *ngFor="let item of pickupCabs">
<app-admin-special-request-allocation-card [allocatedCab]="item" (childevent)="onSpecialRequestReallocation($event)">
</app-admin-special-request-allocation-card>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h5 class="bg-primary text-white">Drop</h5>
</div>
</div>
<div class="row" cdkDropListGroup>
<!-- remove the 'cdkDropList' attribute and [cdkDropListData]=" from below div -->
<div class="col col-md-4" *ngFor="let item of dropCabs">
<app-admin-special-request-allocation-card [allocatedCab]="item" (childevent)="onSpecialRequestReallocation($event)">
</app-admin-special-request-allocation-card>
</div>
</div>
Card Component
<div class="card bg-light shadow p-3 mb-4 bg-white corners mt-2 mb-2">
<div class="card-body text-center">
<div [class.alert-danger]="!isAllocatedSuccess" [class.alert-success]="isAllocatedSuccess" class="alert" *ngIf="isAllocated" >{{message}}</div>
<div class="row">
<div class="col text-right" >
<span><b>{{allocatedCab.AllocationStatusText}}</b></span>
</div>
</div>
<div class="row">
<div class="col-md-3">
<i class='fas fa-{{allocatedCab.CabType|lowercase}}' style='font-size:30px;'></i>
<br>
<b>{{allocatedCab.Occupance}}/{{allocatedCab.Capacity}}</b>
<p><b><span>{{allocatedCab.RouteType}}</span></b></p>
</div>
<!-- Add the cdkDropList attribute and drop list data here -->>
<div class="col-md-9 border-bottom" cdkDropList [cdkDropListData]="allocatedCab.AssignedEmployees" (cdkDropListDropped)="drop($event)">
<div class="row">
<p><b><span>{{allocatedCab.PickupPoint}} To {{allocatedCab.DropPoint}}</span></b></p>
</div>
<div class="row">
<p style="text-align: left"><b><span>{{allocatedCab.VendorName}} - {{allocatedCab.CabName}} - {{allocatedCab.RegNo}}</span></b></p>
</div>
<!-- Add cdkDrag attribute here -->>
<div class="row" *ngFor="let employee of allocatedCab.AssignedEmployees" cdkDrag>
<p style="text-align: left"><span class="fa fa-user"></span>
<a href="./admin#" (click)="open(content,allocatedCab,employee)">
{{employee.FirstName}} {{employee.LastName}} -
<small> {{employee.PickupDate | date: "hh:mm a"}} </small>
</a>
<i style="color:red; cursor: pointer;" class="fa fa-remove" (click)="openConfirmation(content1, employee)"></i></p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 pt-2 text-left ">
<span>{{allocatedCab.PickupDate | date: "dd/MM/yyyy hh:mm a"}}</span>
</div>
</div>
</div>
</div>
It is not mandatory to give cdkDropListGroup and cdkDropList in the same component. When the above code is rendered in the browser, the structure of the cdkDropListGroup and cdkDropList will be set as parent and child relation. So I hope, you may get what you require.

ngIf user is logged in show component

I'm making an app that needs to be accessible for users without an account but as soon as someone makes an account they need to be able to see additional functionality and it needs to be responsive as well.
For responsiveness I'm using material design for bootstrap and angular materialmdbootstrap. In the example bellow I'd want to change the mdb-col-size from 9 to 12 depending on if the user is logged in or not and thus not display save,... option(s).
<div>
<div class="row ">
<div class="col-lg-9 col-md-8 col-sm-6 ">
<div class="row ">
<div class="col-md-12 mb-12">
<div class="card testimonial-card ">
<div class="card-up lighten-1 ">
<div class="card-body">
<h4 class="card-title">{{ dare.title }}</h4>
<hr />
<p>{{ dare.description }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-4 col-sm-6"><!--this shouldn't be displayed when someone is not logged in-->
<div class="row">
<div class="col-12">
<button mat-raised-button class="btn btn-block">
Save
</button>
</div>
</div>
<br />
<div class="row">
<div class="col-12">
<button mat-raised-button class="btn btn-block">
Challenge someone else
</button>
</div>
</div>
<br />
<div class="row">
<div class="col-12">
<button mat-raised-button class="btn btn-block">
Create new ...
</button>
</div>
</div>
</div>
</div>
<br />
</div>
I expect to see the options only when someone is logged in and the responsiveness changing accordingly.
Thanks you in advance!
You should rather use Guards in your project, example in documentation: https://angular.io/api/router/CanActivate
To achieve it you should implement two components (one for authenticated user, another for non-authenticated user). Define routing, for example:
{
path: '',
component: AuthenticatedUserComponent,
canActivate: [AuthenticatedUserGuard]
},
{
path: '',
component: UnauthenticatedUserComponent
}
And then define guard:
#Injectable()
class AuthenticatedUserGuard implements CanActivate {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree {
return true; // here you should call a method from service, that
// that holds whether user is authenticated or not
}
}

Vue Components style display differently on page than when not used as components

I am working on moving chunks of code from being static code within my Views components into actual reusable Components.
I have moved what is called my TrainerCards code into a separate component and the cards used to display nicely as 3 to a row when they were hard coded in my TrainerIndex.vue, but now that they are being passed as a component, they only render as 1 per row, and I don't know why.
TrainerIndex.vue -
<div class="row">
<div class="col-md-4">
<TrainerCards v-for="trainer in orderBy(filterBy(trainers, searchText), sortAttribute, sortAscending)" :key="trainer.id" :trainer="trainer"/>
</div>
</div>
`
TrainerCards.vue -
<template>
<div class="card card-profile">
<div class="card-img-top">
<router-link v-bind:to="'/trainers/' + trainer.id">
<img class="img" :src="(trainer.avatar)" />
</router-link>
</div>
<div class="card-body">
<h4 class="card-title">{{trainer.full_name}}</h4>
<h6 class="card-category">{{trainer.location}}</h6>
<div class="card-footer">
<TrainerTags v-for="tag in trainer.tags" :key="tag.id" :tag="tag"/>
</div>
</div>
</div>
</template>
Any idea on how to get them to display properly?
Your col-md-4 class is what makes them fill 1/3 of the area, but that is now outside your component and not repeating. Move that div inside:
<div class="row">
<TrainerCards v-for="trainer in orderBy(filterBy(trainers, searchText), sortAttribute, sortAscending)" :key="trainer.id" :trainer="trainer"/>
</div>
<template>
<div class="col-md-4">
<div class="card card-profile">
<div class="card-img-top">
<router-link v-bind:to="'/trainers/' + trainer.id">
<img class="img" :src="(trainer.avatar)" />
</router-link>
</div>
<div class="card-body">
<h4 class="card-title">{{trainer.full_name}}</h4>
<h6 class="card-category">{{trainer.location}}</h6>
<div class="card-footer">
<TrainerTags v-for="tag in trainer.tags" :key="tag.id" :tag="tag"/>
</div>
</div>
</div>
</div>
</template>