ngClick on mdListItem and secondary button - javascript

I use angular-material (1.0.7) on my project and I would like to create a clickable list (copied from the official doc) with secondary button.
The main issue is the list-item clickable event is also fired when I click on secondary button. In the doc, they show a dialog with targetEvent but it is not what I try to do.
There is my code:
<md-list-item class="md-2-line" ng-repeat="tag in tagsCtrl.showedTags|orderBy:'title'" ng-click="tagsCtrl.navigate(tag)">
<ng-md-icon icon="label"></ng-md-icon>
<div class="md-list-item-text">
<h3>{{ tag.title }}</h3>
<p>{{ tag.slug }}</p>
</div>
<span class="md-secondary" ng-show="tag.onProcess">
<md-progress-circular md-mode="indeterminate" md-diameter="24"></md-progress-circular>
</span>
<span class="md-secondary" ng-hide="tag.onProcess">
<md-button class=" md-icon-button md-hue-3" ng-click="tagsCtrl.editTag(tag, $event)" aria-label="Edit tag">
<ng-md-icon icon="create"></ng-md-icon>
</md-button>
<md-button class=" md-icon-button md-hue-3" ng-click="tagsCtrl.deleteTag(tag)" aria-label="Delete tag">
<ng-md-icon icon="delete"></ng-md-icon>
</md-button>
</span>
</md-list-item>
The navigation function is not a dialog.
Do you know how I can fix this?

I don't know if I understood it right, but you should stop the propagation of the event from bubbling to its parent (in this case from the md-button to the md-list-item)
Check more documentation here jQuery event.stopPropagation() Method
So where you have:
ng-click="tagsCtrl.editTag(tag, $event)"
ng-click="tagsCtrl.deleteTag(tag)"
you can replace with
ng-click="tagsCtrl.editTag(tag, $event) && $event.stopPropagation()"
ng-click="tagsCtrl.deleteTag(tag) && $event.stopPropagation()"

Related

make a parent div clickable except for a child icon

<div
[ngClass]="{ 'template-row': !isExpandable, 'folder-row': isExpandable }"
class="label-with-icons clickable"
(click)="expanderClicked()"
(click)="itemSelected()"
>
<i *ngIf="isExpandable" [ngClass]="getArrowIconClass()"></i><i [ngClass]="getIconClass()"></i>
<span *ngIf="id" class="name ">{{ name }}</span>
<span *ngIf="!id" class="name">{{ name }}</span>
<i *ngIf="!isExpandable" class="io-icon-trash clickable" id="delete" (click)="deleteTemplate()"></i>
</div>
I want the entire div to be clickable but not the icon with id= delete. I want to have a different click event on that
I dont use jquery , i work with TS
You can stop the event to propagate up in the DOM tree with event.stopPropagation() :
(click)="deleteTemplate($event)"></i>
deleteTemplate(e: Event) {
e.stopPropagation(); // <----event won't travel up
}

AngularJS ng-click multiple calls

I wrote the next code, but when I click on the trash icon, the ng-click of this element is thrown, but the ng-click of the div container is thrown too, I don't need the second one, just the first call, could some body help me.
<div ng-if="order.selectedProducts === null || order.selectedProducts.length > 0"
class="cartCol hoverable" ng-repeat="product in order.selectedProducts track by $index"
ng-click="showProductDetailed(product)">
<div class="cartHeading" ng-bind="product.name"></div>
<a href="" class="trashIcon" ng-click="removeSelectedProduct(product);">
<i class="fa fa-trash"></i>
</a>
<div class="cartSizeInfo">
<span class="fltLft">{{product.productTypeName}}</span>
<span class="fltRht">Bs. {{product.price}}</span>
</div>
</div>
I had to put $event.stopPropagation(); after the first call.

Best practice displaying menu and toolbar in Angular2

I have a webapplication where a user can log into his account. When the user is logged in now the sidenav(menu) and toolbar appears. But when the user isn't logged in (maybe he is going to login or registrate) the toolbar and sidenav should be not visible.
What is the best practice to do that in Angular2(version: 2.1.0 and angular/router version: 3.1.0)
I tried to disable the toolbar and sidenav with ngIf but It doesn't really work and I think it is not a clean solution.
Then I thought about two <router-outlet>. One for the routing when the user is logged in and one when the user is not logged in. Is this the right way to solve my problem? If yes, how does it work?
Here my app.component.html where I define my toolbar, sidenav and the <router-outlet>:
<md-sidenav-layout class="{{themeService.ActualTheme}}" fullscreen>
<div *ngIf="menuToolbarConfigService.ActualPage !== 'landing' && menuToolbarConfigService.ActualPage !== 'register'">
<md-sidenav #sidenav mode="{{menuToolbarConfigService.setSideNav(sidenav)}}">
<div>
<div class="sidenav-header">
<div class="logo-circle">
<span class="logo">GT</span>
</div>
<span class="user-name">Nico</span>
<span class="open-tasks">Offene Tasks: 4</span>
</div>
<md-list>
<div [ngClass]="{'highlight': menuToolbarConfigService.ActualPage === 'start'}" class="nav-list-item">
<md-list-item>
<md-icon>assignment</md-icon> Taskboard
</md-list-item>
</div>
<div [ngClass]="{'highlight': menuToolbarConfigService.ActualPage === 'groups'}" class="nav-list-item">
<md-list-item>
<md-icon>group</md-icon> Gruppen
</md-list-item>
</div>
<div [ngClass]="{'highlight': menuToolbarConfigService.ActualPage === 'user'}" class="nav-list-item">
<md-list-item>
<md-icon>account_circle</md-icon> Benutzer
</md-list-item>
</div>
<div [ngClass]="{'highlight': menuToolbarConfigService.ActualPage === 'user'}" class="nav-list-item">
<md-list-item>
<md-icon>search</md-icon> Taskbrowser
</md-list-item>
</div>
</md-list>
</div>
</md-sidenav>
</div>
<md-toolbar color="primary">
<span *ngIf="menuToolbarConfigService.ShowMenuIcon" (click)="sidenav.open();" class="menu-icon"><md-icon>menu</md-icon></span>
<span class="app-title">GroupTasking</span>
<!-- This fills the remaining space of the current row -->
<span class="example-fill-remaining-space"></span>
</md-toolbar>
<router-outlet></router-outlet>
</md-sidenav-layout>
Thank you in advance!

Ng-click/ ng-repeat issues

I'm trying to create an accordion using angular js and angular material. The problem is that when i'm using ng-repeat, all accordions in the array open when I click the button. I want only want to open the one that i click. Any ideas how I accomplish this? I have tried to google but i'm not finding exactly what i'm looking for
This is my html
<div class="accordionwrapper" layout="column" layout-align="center center">
<div class="accordion" ng-repeat="question in questions">
<div class="accordionheader" layout="row" layout-align="space-between center">
<h3>{{question.q}}</h3>
<md-button class="md-icon-button md-accent" aria-label="Favorite" ng-click="toggleaccordion()" ng-if="!accordionOpen">
<md-icon md-svg-icon="images/add.svg"></md-icon>
</md-button>
<md-button class="md-icon-button md-accent" aria-label="Favorite" ng-click="toggleaccordion()" ng-if="accordionOpen">
<md-icon md-svg-icon="images/minus.svg"></md-icon>
</md-button>
</div>
<div class="accordioncontent" ng-show="accordionOpen">
<p>{{question.a}}</p>
</div>
</div>
And my js
$scope.accordionOpen = false;
$scope.toggleaccordion = function () {
$scope.accordionOpen = !$scope.accordionOpen;
console.log($scope.accordionOpen)
}
Thanks!
You need to keep track of the state of each individual accordion, using an array. This means that accordionOpen should be an array and that toggleaccordion should be like this :
$scope.toggleaccordion = function($index){
$scope.accordionOpen[$index] = !$scope.accordionOpen[$index]
Finally, you should call the function using the $index variable that is provided by angular inside an ng-repeat :
<md-button class="md-icon-button md-accent" aria-label="Favorite" ng-click="toggleaccordion($index)" ng-if="accordionOpen[$index]">
All your accordions created by using ng-repeat depend on one variable, which is accordionOpen. Create an array of boolean flags and put it into questions array so that each of the accordions would have its own flag.
When you're calling $scope.accordionOpen = !$scope.accordionOpen; the scope is the parent of all the ngRepeat scopes. They inherit the accordionOpen value.
There might be more solutions to this - set the accordionOpen = true in ngClick instead of calling controller function: EDIT: Note: This won't probably work because the md-button ng-if uses it's own scope. It's always better to stick to some kind of model object, that other answers or second solution suggest.
<md-button
class="md-icon-button md-accent"
aria-label="Favorite"
ng-click="accordionOpen = true"
ng-if="!accordionOpen">
<md-icon md-svg-icon="images/add.svg"></md-icon>
</md-button>
or add a property to the question itself
js:
$scope.toggleaccordion = function (question) {
question.$accordionOpen = !question.$accordionOpen;
}
html
<md-button ng-click="toggleaccordion(question)" ng-if="!question.$accordionOpen">
<md-icon md-svg-icon="images/add.svg"></md-icon>
</md-button>
<div class="accordioncontent" ng-show="question.$accordionOpen">
<p>{{question.a}}</p>
</div>
Read more on scopes: https://docs.angularjs.org/guide/scope
You are using a single variable in scope to toggle a collection of accordian , because of this all accordians toggle on the change of single varialbe .
To avoid it every accordian should have it's own set of toggle flag.To achieve it keep the flag with the record itself( in your case the question object)
<div class="accordionheader" layout="row" layout-align="space-between center">
<h3>{{question.q}}</h3>
<md-button class="md-icon-button md-accent" aria-label="Favorite" ng-click="toggleaccordion(question)" ng-if="!question.accordionOpen">
<md-icon md-svg-icon="images/add.svg"></md-icon>
</md-button>
<md-button class="md-icon-button md-accent" aria-label="Favorite" ng-click="toggleaccordion(question)" ng-if="question.accordionOpen">
<md-icon md-svg-icon="images/minus.svg"></md-icon>
</md-button>
</div>
<!-- In ng-show use a variable which will make sure that every object will get it's own toggle status field -->
<div class="accordioncontent" ng-show="question.accordionOpen">
<p>{{question.a}}</p>
</div>
</div>
And in your js use like this
$scope.questions.forEach(function(question){
question.accordionOpen = false ;
});
$scope.toggleaccordion = function (question) {
question.accordionOpen = !question.accordionOpen;
}

angular material dialog opened on ng-repeat element

I have an array of elements used with ng-repeat. Each element contains md-card directive with ng-click directive that call a function that open angular material dialog window.
After dialog opening my scroll go to the top. But it happens only once after reloading page. Same behavior when I use $mdDialog.hide(result) in dialog controller.
here my html.
<div layout="row" ng-if="!isLoading" ng-repeat="booking in calendarCtrl.currentBookings | orderBy:'start'">
<div class="time" flex="15" layout="column" layout-align="start end">
<span ng-bind="::booking.start"></span>
<span ng-bind="::calendarCtrl.calculateEndTime(booking.start,booking.time)"></span>
</div>
<md-card flex ng-click="calendarCtrl.openDialog(booking,$event)">
<md-card-header>
<md-card-avatar>
<img ng-src="imgs/logo.png" class="md-user-avatar" alt="img"/>
</md-card-avatar>
<md-card-header-text layout="row">
<span flex class="md-title" ng-bind="::booking.client"></span>
<span ng-if="!booking.confirmed" class="isUnread"></span>
</md-card-header-text>
</md-card-header>
<div class="service" layout="column">
<span class="md-body-1">
<span ng-if="booking.phone" ng-bind="::booking.phone"></span>
<span ng-if="booking.phone && booking.email"> | </span>
<span ng-if="booking.email" ng-bind="::booking.email"></span>
</span>
<span ng-style="calendarCtrl.setColor(booking.reservationTypeName,0.5)">
<span class="circle" ng-style="calendarCtrl.setColor(booking.reservationTypeName,1)"></span>
<span class="text" ng-bind="booking.reservationTypeName"></span>
</span>
</div>
<div ng-if="calendarCtrl.checkComment(booking.comment)">
<hr/>
<md-card-content>
<div class="description">
<p ng-bind="::booking.comment"></p>
</div>
</md-card-content>
</div>
</md-card>
</div>
and function calendarCtrl.openDialog(booking,$event)
function openDialog(booking,event){
dialogService.openDialog(booking,event,self.reservationTypes.get(booking.reservationTypeName))
.then(function(answer) {
console.log(`You confirm booking with id: ${answer.id}`);
console.log(answer)
}, function() {
console.log('You close the dialog.');
});
}
and dialogService.openDialog function
function openDialog(booking,event,color){
return $mdDialog.show({
templateUrl: 'dialog/dialog.html',
controller: 'dialogController',
controllerAs: 'dialogCtrl',
parent: angular.element(document.body),
targetEvent: event,
clickOutsideToClose:true,
locals:{
booking:booking,
color:color
}
})
}
Please help.

Categories

Resources