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.
Related
I am having trouble to access angularjs expressions after the click event.
index.html
<div class="row">
<a href="#/company"><div class="tile col col-comp cat-a-g grow-appear" ng-click="onSelect(item)" ng-repeat="item in data" >
<p>{{item.compname}}</p>
</div></a>
</div>
The above code populate a list of company names. When I click on a company it opens company.html
company.html
<div class="comp-info col s12 grow-appear">
<span class="comp-logo-container">
<img src="images/aap3-160x70-black.jpg" />
</span>
<span class="comp-info-container">
<p><i class="far fa-envelope"></i>{{item.compemail}}</p>
<p><i class="fas fa-location-arrow"></i>{{item.compbuilding}}</p>
<p><i class="fas fa-phone"></i>{{item.compphone}}</p>
</span>
</div>
Controller (app.js)
$scope.onSelect = function($event, data) {
console.log(data);
}
File Structure
root
+--public
+--templates
+--company.html
+--index.html
+--javascript
+--app.js
+--views
+main.html
I am using ngRoute to inject index.html and company.html into main.html.
app.config(function($routeProvider){
$routeProvider
.when ('/', {
templateUrl: 'templates/home.html',
controller: 'AppCtrl'
})
.when ('/company', {
templateUrl: 'templates/company.html',
controller: 'AppCtrl'
})
});
So when I console.log() the controller, it shows the array of data but it doesn't add it to the company html document. What am I missing?
The structure of your application is a little unclear, but I think your problem may be to do with $scope. item in item in data is not accessible from the root of $scope. You can do something like this:
<div class="comp-info col s12 grow-appear">
<span class="comp-logo-container">
<img src="images/aap3-160x70-black.jpg" />
</span>
<span class="comp-info-container">
<p><i class="far fa-envelope"></i>{{selected.compemail}}</p>
<p><i class="fas fa-location-arrow"></i>{{selected.compbuilding}}
</p>
<p><i class="fas fa-phone"></i>{{selected.compphone}}</p>
</span>
</div>
Then:
$scope.onSelect = function($event, data) {
$scope.selected = data;
}
I have a directive to click on an item and can later be edited. This directive is called click-to-edit. I'm doing an ng-repeat, and every row is an accordion. My idea is to cick the edit button, and I can edit the text, as if I clicked on it.
how can I do it?
<uib-accordion close-others="true">
<div ng-repeat="faq in faqs">
<div class="col-sm-11" >
<div uib-accordion-group class="panel-default" is-open="faq.open">
<uib-accordion-heading >
<span ng-click="ignoreClick($event);" ><a href='' click-to-edit ng-model='faq.pregunta' typeinput='textarea' >{{faq.pregunta}}</a></span> <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': faq.open, 'glyphicon-chevron-right': !faq.open}"></i>
</uib-accordion-heading>
<span click-to-edit ng-model="faq.respuesta" >{{faq.respuesta}}</span>
</div>
</div>
<div class="col-sm-1" >
<button type="button" class="btn btn-default">
<span class="glyphicon glyphicon glyphicon-edit"></span>
</button>
</div>
</div>
</uib-accordion>
https://plnkr.co/edit/K5fXaIzSBkV91V7AFoqw?p=preview
Instead of initializing scope.editState = false inside the directive, you can pass it in from your controller.
Set up your directive to take editState as a parameter:
scope: {
model: '=ngModel',
editState: '='
}
Create an editState variable on each faq in your controller, with a function to toggle it:
Controller:
$scope.faqs=[
{"pregunta": "pregunta1", "respuesta": "respuesta1", "open":true, "editState": false},
{"pregunta": "pregunta2", "respuesta": "respuesta2", "open":false, "editState": false},
{"pregunta": "pregunta3", "respuesta": "respuesta3", "open":false, "editState": false}
];
$scope.toggleEditState = function(index) {
$scope.faqs[index].editState = !$scope.faqs[index].editState;
}
Controller's template:
<a click-to-edit edit-state='faq.editState' ... >
<button ng-click="toggleEditState($index)"></button>
Here is a plnkr.
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!
My template:
<template id="players-template" inline-template>
<div v-for="player in players">
<div v-bind:class="{ 'row': ($index + 1) % 3 == 0 }">
<div class="player col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{{ player.username }}
<span class="small pull-right">{{ player.createdAt }}</span>
</h3>
</div>
<div class="panel-body">
<img v-bind:src="player.avatar" alt="{{ player.username }}" class="img-circle center-block">
</div>
<div class="panel-footer">
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<span class="glyphicon glyphicon-envelope"></span>
<span class="glyphicon glyphicon-user"></span>
<span class="glyphicon glyphicon-option-horizontal"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
My script:
new Vue({
el: 'body',
methods: {
createConversation: function(id) {
console.log("createConversation()");
console.log(id);
}
}
});
When the template is rendering i gets an error [Vue warn]: v-on:click="createConversation" expects a function value, got undefined. I don't know how to use methods inside a component template. If someone could help me I would appreciate is.
If you need the createConversation method to be on the global Vue instance, you should look at dispatching events. Your component should like this:
Vue.component('playersTemplate', {
template: '#players-template',
methods: {
createConversation: function (id) {
this.$dispatch('createConversation', id)
}
}
}
});
The global Vue instance should implement the createConversation event, instead of a method:
new Vue({
el: 'body',
events: {
createConversation: function(id) {
console.log("createConversation()");
console.log(id);
}
}
});
Your method should be in the component, not in your global Vue instance. All functions are called as this.createConversation behind the scenes, so it needs to be within the component that is the template for.
I'm using pageslide directive in order to display a lateral sliding menu when I click on an icon.
This is the usual way to do it, and its working :
<div class="navbar-header">
<span ng-controller="slideController as s">
<a class="navbar-brand" href="javascript:void(0)"
ng-click="s.toggle()"><i class="fa fa-bars fa-lg"></i></a>
<div pageslide ps-open="s.isActive" ps-side="left">
<div style="padding:20px">
<h2>Hello Pageslide</h2>
<p>Put here whatever I want in the lateral menu</p>
<a ng-click="s.toggle()" class="button" >Close</a>
</div>
</div>
</span>
<a class="navbar-brand text-danger" href="javascript:void(0)">Balrog</a>
</div>
But I would lilke to make the menu content in an external template, so I'm trying this :
<div class="navbar-header">
<span ng-controller="slideController as s">
<a class="navbar-brand" href="javascript:void(0)"
ng-click="s.toggle()"><i class="fa fa-bars fa-lg"></i></a>
<menu-item isActive="s.isActive"></menu-item>
</span>
<a class="navbar-brand text-danger" href="javascript:void(0)">Balrog</a>
</div>
with this as menu.html :
<div pageslide ps-open="s.isActive" ps-side="left">
<div style="padding:20px">
<h2>Hello Pageslide</h2>
<p>Put here whatever I want in the lateral menu</p>
<a ng-click="s.toggle()" class="button" >Close</a>
</div>
</div>
also, here is the related controller :
'use strict';
angular.module('BalrogApp').controller('slideController', function(){
this.isActive= false; // This will be binded using the ps-open attribute
this.toggle = function(){
this.isActive= !this.isActive
}
});
and the <menu-item> directive :
angular.module('BalrogApp').directive('menuItem', function () {
return {
restrict: 'E',
templateUrl: "views/menu.html",
scope: {
isActive: '='
},
controller: 'slideController',
controllerAs: 's',
bindToController: true
}
});
So it's not working this way, maybe it is because the main view (including the <menu-item>) is itself included in the main page thanks to <ng-view> ?
Or maybe the pageslide-directive requires the <div pageslide ...> and its parent element to be on the same file ?
I can tell from the console that toggle() is called and changes isActive in both cases but it's not opening the menu with the directive version.
And also, adding ng-controller="slideController as s" to the root <div> with the pageslide attribute didn't change anything.
So how can I make this work with the menu in another file ?
Did you try to replace <div ng-include="menu.html"></div> with <div ng-include="'menu.html'"></div>. According to https://docs.angularjs.org/api/ng/directive/ngInclude, you have to wrap string constants in single quotes.
I highly recommend you not use ng-include. You can get the same approach using directive instead.
For example:
Menu html
<div pageslide ps-open="vm.checked" ps-side="left">
<div style="padding:20px">
<h2>Hello Pageslide</h2>
<p>Put here whatever I want in the lateral menu</p>
<a ng-click="vm.toggle()" class="button" >Close</a>
</div>
</div>
Directive:
function Controller() {
}
Controller.prototype.toggle = function() {
this.checked = !this.checked;
}
angular
.module('BalrogApp')
.directive('menuItem', function() {
return {
templateUrl: 'urltomenu.html',
restrict: 'E',
scope: {
checked: '='
},
controller: Controller,
controllerAs: 'vm',
bindToController: true
}
})
Main template
<div class="navbar-header">
<span ng-controller="slideController as s">
<a class="navbar-brand" href="javascript:void(0)"
ng-click="s.toggle()"><i class="fa fa-bars fa-lg"></i></a>
<menu-item checked="s.checked"><menu-item>
</span>
<a class="navbar-brand text-danger" href="javascript:void(0)">Balrog</a>
</div>
This approach give you more power. All the logic is inside the directive controller and you could reuse this element each time. The scope attribute checked is the "bridge" between your main template if change outside also change inside and also the other way.