ng-click not firing in md-bottom-sheet - angularjs

My apologies in advance for a lengthy post. I wanted to include as much data as possible to see if you could assist me in my problem.
I originally developed the project using Bootstrap as a prototype and proof of concept. Now that I'm planning on going into production, I wanted to use angular-material.
Everything worked perfectly in Bootstrap. However, now that I'm using material design, ng-click is not working now that I'm using md-bottom-sheet. Here is the full code snippets;
HTML
index.html
<html ng-app="teamApp">
<head>
<link href="https://ajax.googleapis.com/ajax/libs/angular_material/0.9.4/angular-material.min.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
</head>
<body layout-fill layout-margin layout-padding layout="column" ng-controller="TeamController as teamCtrl">
<md-toolbar layout="row">
<div class="md-toolbar-tools">
<md-button class="md-icon-button" hide-gt-sm ng-click="toggleSidenav('left')">
<md-icon aria-label="Menu" md-svg-icon="https://s3-us-west-2.amazonaws.com/s.cdpn.io/68133/menu.svg"></md-icon>
</md-button>
<h2>Team Builder</h2>
</div>
</md-toolbar>
<div flex layout="row">
<md-sidenav class="md-sidenav-left md-whiteframe-z2" layout="column" md-component-id="left" md-is-locked-open="$mdMedia('gt-sm')">
<md-toolbar layout="row">
....
</md-toolbar>
<md-list>
....
</md-list>
</md-sidenav>
<div flex id="content" layout="column">
<md-content class="md-padding" flex layout="column">
<!-- Custom Directive to team-form.html -->
<team-forms></team-forms>
</md-content>
</div>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/0.10.1/angular-material.min.js"></script>
<script src="js/team.js"></script>
</body>
</html>
You will see the team-forms directive. This is a custom directive that pulls in team-form.html. team-form.html has the button that when clicked pops up the md-bottom-sheet.
team-form.html
<div class="teamForms" layout="column">
<div id="team-list" class="row" flex>
<md-list>
<md-subheader class="md-no-sticky">Teams</md-subheader>
<md-list-item ng-repeat="team in teams">
........
</md-list-item>
</md-list>
</div>
<!-- button that when click, makes md-bottom-sheet pop up -->
<md-button class="md-fab" style="position:absolute; right:0; bottom:0" aria-label="Add Team" ng-click="teamCtrl.showAddTeam($event)">
<span style="font-size:3em; line-height:1.2em">+</span>
</md-button>
</div>
The HTML template used for the md-bottom-sheet is team-add.html. This is what pops up when the button above is clicked.
team-add.html
<!-- FORM TO CREATE team -->
<md-bottom-sheet>
{{formData}}
<md-toolbar layout="row">
<div class="md-toolbar-tools">
<h2>Add Team</h2>
</div>
</md-toolbar>
<form name="add-team">
<md-content layout-padding layout-sm="column" layout="row">
<md-input-container>
<label>Team Name</label>
<input name="teamName" ng-model="formData.name" required type="text">
</md-input-container>
</md-content>
<div layout="row" ng-show="formData.name.length >= 1">
<md-input-container>
<label>Employee Name</label>
<input class="form-control" name="teamEmployee" ng-model="employee.name" type="text">
</md-input-container>
<md-button class="md-raised md-primary" ng-click="addEmployee(formData)" type="submit">Add</md-button>
</div>
<md-content layout="row">
<md-input-container>
<md-button class="md-raised md-primary" ng-click="teamCtrl.createTeam()">Add Team</md-button>
</md-input-container>
</md-content>
</form>
</md-bottom-sheet>
JS
team.js
(function() {
'use strict';
var app = angular.module("teamApp", ["ngMaterial"]);
app.controller("TeamController", ["$scope", "$http", "$mdSidenav", "$mdBottomSheet", function($scope, $http, $mdSidenav, $mdBottomSheet) {
$scope.formData = {};
$scope.formData.employees = [];
// when landing on the page, get all teams and show them
$http.get("/api/teams")
.success(function(data) {
$scope.teams = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
$scope.toggleSidenav = function(menuId) {
$mdSidenav(menuId).toggle();
};
this.showAddTeam = function($event) {
$mdBottomSheet.show({
templateUrl: 'directives/team/team-add.html',
targetEvent: $event
})
};
this.resetForms = function() {
$scope.teamForm = false;
$scope.employeeForm = false;
};
this.getTeam = function(id) {
$http.get("/api/teams/" + id)
.success(function(data) {
$scope.singleTeam = data;
console.log('Success: ' + data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
// when submitting the add form, send the text to the node API
this.createTeam = function() {
$http.post("/api/teams", $scope.formData)
.success(function(data) {
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.formData.employees = [];
$scope.teams = data;
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
this.updateTeam = function(id) {
$http.put("/api/teams/" + id, $scope.singleTeam[0])
.success(function(data) {
$scope.singleTeam = {};
$scope.teams = data;
console.log('Success: ' + data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
// delete a todo after checking it
this.deleteTeam = function(id) {
$http.delete("/api/teams/" + id)
.success(function(data) {
$scope.teams = data;
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
this.getRotation = function() {
$http.post("/api/rotations")
.success(function(data) {
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
}]);
app.directive("teamForms", function() {
return {
restrict: "E",
templateUrl: "directives/team/team-forms.html",
controller: ["$scope", function($scope) {
$scope.employee = {};
$scope.teamForm = false;
$scope.employeeForm = false;
this.showTeamForm = function(value) {
return $scope.teamForm == value;
};
this.setTeamForm = function(value) {
$scope.teamForm = value;
};
this.showEmployeeForm = function(value) {
return $scope.employeeForm == value;
};
this.setEmployeeForm = function(value) {
$scope.employeeForm = value;
};
$scope.addEmployee = function(dataSet) {
dataSet.employees.push($scope.employee);
$scope.employee = {};
};
$scope.removeEmployee = function(dataSet, index) {
dataSet.employees.splice(index, 1);
};
}],
controllerAs: "teamFormCtrl"
};
});
app.directive("teamEditForm", function() {
return {
restrict: "E",
templateUrl: "directives/team/team-edit.html"
};
});
}());
The issue is in the team-add.html. It's the md-button that is trying to call createTeam().
The expected result is that it would post the name of the team to my API endpoint and into my mongoDB setup. This was working perfectly before in bootstrap but I feel that now I'm deeper in the UI with how md-bottom-sheet needs to be setup, that I have some scoping or controller issue in place.
I have even tried adding a fake, non-existent function to ng-click to see if some error was thrown when clicked but no error showed up. Node is not even reporting a post command being sent. It just seems that the button is doing absolutely nothing
Any help would be greatly appreciated and if more code is needed, please let me know and I'll post it up!
Thanks!

In your md-button your ng-click is something like this
<md-button class="md-fab"
ng-click="teamCtrl.showAddTeam($event)">
Your question reads "ng-click not firing", to make ng-click work give this a try
ng-click="showAddTeam($event)">
This will work since you are trying to call a function which is in some controller and your directive's html is within at controller's scope only.

Related

Method binding is not working in Angular

I am trying to attached a controller scope method in a directive but when i click in directive button that linked method is not called. Please review code. There is side-nav directive in which i have attached method with select parameter. but when button is clicked method is not called.
index.html
<div class="container" layout="row" flex ng-controller="userController as vm" ng-init="vm.loadUsers()">
<md-sidenav md-is-locked-open="true" class="md-whiteframe-1dp">
<side-nav users="vm.users" select="vm.selectUser(user)"></side-nav>
</md-sidenav>
<md-content id="content" flex>
<user-detail selected="vm.selected" share="vm.share()"></user-detail>
</md-content>
</div>
userController.js
app.controller("userController", ['$scope', 'userService', '$mdBottomSheet', function ($scope, userService, $mdBottomSheet) {
var self=this;
self.users = [];
this.name = "manish";
self.loadUsers = function () {
userService
.loadAllUsers()
.then(function (users) {
self.users = users;
self.selected = users[0];
userService.selectedUser = self.selected;
});
}
self.selectUser = function (user) {
self.selected = user;
userService.selectedUser = self.selected;
}
}]);
directives.js
app.directive("sideNav", function () {
return {
restrict :'AE',
templateUrl: './views/sidenav.html',
scope : {
select : '&',
users : '='
}
}
});
./views/sidenav.html
<md-list>
<md-list-item ng-repeat="user in users">
<md-button ng-click="select({user:user)">
<md-icon md-svg-icon="{{user.avatar}}" class="avatar"></md-icon>
{{user.name}}
</md-button>
</md-list-item>
</md-list>
Try doing it like this:
index.html
<side-nav users="vm.users" select="vm.selectUser"></side-nav>
./views/sidenav.html
<md-button ng-click="select()(user)">

Cofigure Height of the Angular Material inputs

I need to modify the height of the Angular-Material inputs to the minimun.
This is because i need to insert many inputs in a small box (500px and it is positioned on bottom of the screen), but I need that the height of the inputs do not change the height of the box, then i need that one of two things DO NOT HAPPEN:
1- The box grows-down wich is causing that the send button and other inputs are offscreen.
2- If the height of the box is configured with percentage (height:80%), then appears a scroll control in the right border of the box.
Here is the code:
<!doctype html>
<html lang="en">
<head>
<title>FORM</title>
<!-- Firebase -->
<script src="https://cdn.firebase.com/js/client/2.2.4/firebase.js"></script>
<!-- AngularFire -->
<script src="https://cdn.firebase.com/libs/angularfire/1.2.0/angularfire.min.js"></script>
<!-- Angular Material style sheet -->
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.css">
</head>
<body ng-app="mmadera">
<div class="box" style="position:relative; width:500px; height:500px;">
<div ng-controller="DemoCtrl" layout="column" ng-cloak="" class="md-inline-form inputdemoBasicUsage" >
<md-content md-theme="docs-dark" layout-gt-sm="row" layout-padding="">
<div>
<md-input-container flex-gt-sm="">
<label>Título</label>
<input ng-model="user.titulo">
</md-input-container>
<md-input-container flex-gt-sm="">
<label>Email</label>
<input ng-model="user.email" type="email">
</md-input-container>
</div>
</md-content>
<md-content layout-padding="">
<div>
<form name="userForm">
<div layout-gt-xs="row">
<md-input-container flex-gt-xs=""> <!-- class="md-block" disabled="" -->
<label>Empresa</label>
<input ng-model="user.empresa" >
</md-input-container>
</div>
<div layout-gt-sm="row">
<md-input-container class="md-block" flex-gt-sm="">
<label>Nombre</label>
<input ng-model="user.nombre">
</md-input-container>
<md-input-container class="md-block" flex-gt-sm="">
<label>Teléfono</label>
<input ng-model="user.nombre">
<!-- ng-model="theMax" -->
</md-input-container>
</div>
<md-input-container class="md-block">
<label>Dirección</label>
<input ng-model="user.direcdion">
</md-input-container>
<div layout-gt-sm="row">
<md-input-container class="md-block" flex-gt-sm="">
<label>País</label>
<input ng-model="user.pais">
</md-input-container>
<md-input-container class="md-block" flex-gt-sm="">
<label>Estado</label>
<input ng-model="user.estado">
</md-input-container>
</div>
<md-input-container class="md-block">
<label>Mensaje</label>
<textarea ng-model="user.mensaje" md-maxlength="150" rows="5" md-select-on-focus=""></textarea>
</md-input-container>
<div>
<md-button type="submit" >ENVIAR</md-button>
</div>
</form>
</div>
</md-content>
</div>
</div>
<!-- ............................. ANGULAR - A.MATERIAL ......................................-->
<!-- Angular Material requires Angular.js Libraries -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-animate.js"></script>
<!-- Angular Material Library -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.js"></script>
<!-- Your application bootstrap -->
<script type="text/javascript">
angular.module('mmadera',['ngMaterial','ngMessages'])
.controller('SwitchDemoCtrl', function($scope) {
$scope.data = {
cb1: true,
cb4: true,
cb5: false
};
$scope.message = 'false';
$scope.onChange = function(cbState) {
$scope.message = cbState;
};
})
/* __________________________ PANEL js __________________________*/
/* __________________________ FOOTER __________________________*/
.controller('footsoc', function($scope) {
$scope.abre = false;
$scope.mov = {
isOpen: false,
count: 0,
selectedDirection: 'right'
};
})
/* __________________________ FOOTER __________________________*/
/* __________________________ SIDE BAR (Proceso) __________________________*/
.controller('AppCtrl', function ($scope, $timeout, $mdSidenav, $log) {
$scope.toggleLeft = buildDelayedToggler('left');
$scope.toggleRight = buildToggler('right');
$scope.isOpenRight = function(){
return $mdSidenav('right').isOpen();
};
/**
* Supplies a function that will continue to operate until the
* time is up.
*/
function debounce(func, wait, context) {
var timer;
return function debounced() {
var context = $scope,
args = Array.prototype.slice.call(arguments);
$timeout.cancel(timer);
timer = $timeout(function() {
timer = undefined;
func.apply(context, args);
}, wait || 10);
};
}
/**
* Build handler to open/close a SideNav; when animation finishes
* report completion in console
*/
function buildDelayedToggler(navID) {
return debounce(function() {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav(navID)
.toggle()
.then(function () {
$log.debug("toggle " + navID + " is done");
});
}, 200);
}
function buildToggler(navID) {
return function() {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav(navID)
.toggle()
.then(function () {
$log.debug("toggle " + navID + " is done");
});
}
}
})
.controller('LeftCtrl', function ($scope, $timeout, $mdSidenav, $log) {
$scope.close = function () {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav('left').close()
.then(function () {
$log.debug("close LEFT is done");
});
};
})
.controller('RightCtrl', function ($scope, $timeout, $mdSidenav, $log) {
$scope.close = function () {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav('right').close()
.then(function () {
$log.debug("close RIGHT is done");
});
};
})
.controller('DemoCtrl', function() {
this.isOpen = false;
this.availableModes = ['md-fling', 'md-scale'];
this.selectedMode = 'md-fling';
this.selectedDirection = 'right';
})
.controller('DropdownCtrl', function ($scope, $log) {
$scope.items = [
'The first choice!',
'And another choice for you.',
'but wait! A third!'
];
$scope.status = {
isopen: false
};
$scope.toggled = function(open) {
$log.log('Dropdown is now: ', open);
};
$scope.toggleDropdown = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.status.isopen = !$scope.status.isopen;
};
$scope.appendToEl = angular.element(document.querySelector('#dropdown-long-content'));
})
.controller('DemoCtrl', function($scope) {
$scope.user = {
titulo: 'Quiero vender mas!',
email: 'ejemplo#koomkin.com',
nombre: '',
telefono: '',
empresa: 'Koomkin',
direccion: '1600 Amphitheatre Pkwy',
pais: 'México',
estado: 'CDMX',
mensaje: 'Escribe tu mensaje',
postalCode: '94043'
};
})
.config(function($mdThemingProvider) {
// Configure a dark theme with primary foreground yellow
$mdThemingProvider.theme('docs-dark', 'default')
.primaryPalette('yellow')
.dark();
});
</script>
</body>
</html>
THANK YOU.
If the height of the box must not change, apply the max-heightstyle to it, with the overflow property too.
the max-height will fix your box height, while the overflow property set to hidden will hide elements that are out of it, and won't give you a scrollbar.
To change the inputs height, give them a class like this :
<input ng-model="user.titulo" class="myInput">
and give them a height of your own.
FYI, the class that applies the height of an input is md-container .md-input, so you can either overwrite it or add a new class like I told you before.
Depending on how you import your css sheets, you may need to use the !importantproperty on your class like so :
.myInput {
height: 20px !important;
max-height: 20px !important;
}

Pushing item to array after close md-dialog not working

Array does not refresh after pushing item through md-dialog, though I can save the item normally.
I tried to test which level I could push an item into the array manually and I could do so until $scope.showAddUsuario(), after that I can't push an item, even manually:
Usuario.html
<div flex-gt-sm="100" flex-gt-md="100" ng-controller="UsuarioCtrl">
<h2 class="md-title inset">Usuario</h2>
<md-card>
<md-list>
...
</md-list>
</md-card>
<md-button class="md-fab" aria-label="Add" ng-click="showAddUsuario($event)">
<md-icon md-svg-icon="content:ic_add_24px" aria-label="Plus"></md-icon>
</md-button>
</div>
md-dialog:
<md-dialog aria-label="Form">
<md-content class="md-padding">
<form name="userForm">
<div layout layout-sm="column">
<md-input-container flex> <label>Nome</label> <input ng-model="item.nome"> </md-input-container>
</div>
<div layout layout-sm="column">
<md-input-container flex> <label>E-mail</label> <input ng-model="item.email"> </md-input-container>
</div>
<div layout layout-sm="column">
<md-input-container flex> <label>Senha</label> <input ng-model="item.senha"> </md-input-container>
</div>
</form>
</md-content>
<div class="md-actions" layout="row">
<span flex></span>
<md-button ng-click="cancel()"> Cancel </md-button>
<md-button ng-click="saveUsuario(item)" class="md-primary"> Save </md-button>
</div>
</md-dialog>
Controller:
app.controller('UsuarioCtrl', function ($scope, $http, $mdDialog, $interval, $timeout) {
$scope.items = [];
$http({
method : 'GET',
url : 'UsuarioServlet'
})
.success(
function(data, status, headers,
config) {
$scope.items = data;
}).error(
function(data, status, headers,
config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
$scope.saveUsuario = function(item) {
$scope.items.push({id:100, nome:item.nome, email:item.email, senha:item.senha, status:1});
};
$scope.showAddUsuario = function(ev) {
$mdDialog.show({
controller: 'UsuarioCtrl',
templateUrl : 'CrudUsuario.html',
targetEvent : ev,
locals : {
item : null
}
})
};
});
Only now do I see that you were using $mdDialog and not $modal. So this answer will most likely not apply to your case.
You do however seem to be missing a .finally() part in your code.
From the manual ( https://material.angularjs.org/latest/api/service/$mdDialog )
$mdDialog
.show( alert )
.finally(function() {
alert = undefined;
});
So you could try that.
Otherwise, have you considered using $modal instead?
You don't seem to be handling the return of information from your modal.
(function (){
'use strict';
function myCtrl($modal){
var vm = this;
vm.myArray = [];
...
function openModal(){
var modalInstance = $modal.open({
templateUrl: 'path/to/modal/view.html',
controller: 'MyModalCtrl as vm',
size: 'lg',
resolve: {
data: function(){
return dataThatYouWantToSendFromHereToYourModal;
}
}
});
modalInstance.result.then(function (result){
vm.myArray.push(result);
});
}
...
}
...
})();
The modalIntsance.result.then will trigger when you in your modal-controller (in this case MyModalCtrl) issues a $modalInstance.close(sendThisDataBackToCallingController) call.
So the modal-controller should look along the lines of
...
function MyModalCtrl($modalInstance, data){
...
function init(){
doSomethingWithDataThatYouGotFromTheCallingController(data);
}
...
function save(){
var dataToSendBack = {...};
$modalInstance.close(dataToSendBack);
}
...
}
...
That should get you going in the right direction.
Thanks for the comments! The documentation say to use that:
}).then(function(item) {
$scope.items.push({id:100, nome:item.nome, email:item.email, senha:item.senha, status:1});
});
Works fine!
I solve this problem ,Please replace $mdDialog.show() as
$mdDialog.show({
controller: function (){
this.parent = $scope;
},
templateUrl: 'dialog1.tmpl.html',
scope:$scope.$new(),
targetEvent : ev,
bindToController: true,
clickOutsideToClose:true,
fullscreen: useFullScreen
})

Can't get md-autocomplete to display on the page as it does in the angular-material example

I've been able to hook up angular materials autocomplete directive up to my data source and to display the information that I want, however I am unable to make the list of results display in the same way it does here:
https://material.angularjs.org/#/demo/material.components.autocomplete
My results appear like this:
http://i.imgur.com/3iMiXo5.png
Also, when I click away from the search box the autocomplete suggestions disappear and do not reappear on refocusing.
My HTML:
<div ng-controller="RoutesCtrl as ctrl" id="mainDiv" layout="column">
<div layout="row" flex>
<div layout="column" flex id="content">
<md-content>
<md-toolbar>
<div class="md-toolbar-tools header-color">
<md-button class="md-fab md-primary button-color" >
<md-icon class="ng-scope ng-isolate-scope md-default-theme hamburger-icon" aria-label="Menu" style="height: 14px; width: 14px;" md-svg-src="/assets/icons/ic_menu_18px.svg"></md-icon>
</md-button>
<md-button class="md-icon-button" aria-label="Settings"></md-button>
<h1 class="md-display-4"></h1>
</div>
</md-toolbar>
</md-content>
<md-content layout-padding layout="column">
<form ng-submit="$event.preventDefault()">
<md-autocomplete
md-items="item in ctrl.querySearch(ctrl.searchText)"
md-selected-item-change="ctrl.selectedItemChange(item)"
md-search-text-change="ctrl.searchTextChange(ctrl.searchText)"
md-search-text="ctrl.searchText"
md-selected-item="ctrl.selectedItem"
md-item-text="item.from_where + ' to ' + item.to_where"
placeholder="Search for a route"
md-no-cache="ctrl.noCache"
ng-disabled="ctrl.isDisabled"
md-min-length="3"
md-delay="0"
md-autoselect="true">
<span md-highlight-text="ctrl.searchText" md-highlight-flags="^i">{{item.from_where + ' to ' + item.to_where}}</span>
</md-autocomplete>
</form>
</md-content>
<div ng-controller="MapController">
<leaflet center="center"></leaflet>
</div>
</div>
</div>
</div>
The html that mine generates does not have the ng-focus attribute or the class "ng-scope".
The service I am using to grab my data:
App.service('route', function route($http, $q){
var route = this;
route.routeList = {};
route.getAllRoutes = function(){
var defer = $q.defer();
$http.get('/routes')
.success(function(response){
route.routeList = response;
defer.resolve(response);
})
.error(function(error, status){
defer.reject(error);
});
return defer.promise;
};
return route;
});
And the controller:
App.controller("RoutesCtrl", function($scope, route, $timeout, $q, $log, $http){
$scope.init = function() {
$scope.getAll();
};
$scope.getAll = function(){
route.getAllRoutes()
.then(function(response){
//success
self.routes = response;
return route.routeList;
}, function(error) {
//error
}, function(message) {
//message
});
};
var self = this;
self.searchText = null;
self.querySearch = querySearch;
self.simulateQuery = true;
self.isDisabled = false;
self.selectedItemChange = selectedItemChange;
self.searchTextChange = searchTextChange;
self.selectedItem = null;
function querySearch (q) {
var results = q ? self.routes.filter(createFilterFor(q) ) : [],
deferred;
if (self.simulateQuery) {
deferred = $q.defer();
$timeout(function() { deferred.resolve( results ); }, Math.random() * 1000, false);
return deferred.promise;
} else {
return results;
}
}
function searchTextChange (text) {
$log.info('Text changed to ' + text);
}
function createFilterFor(query) {
var lowerCaseQuery = angular.lowercase(query);
return function FilterFn(route) {
return (route.route_from_to.toLowerCase().indexOf(lowerCaseQuery) === 0);
};
}
function selectedItemChange (item) {
if (!item) {
return
} else {
console.log(self.selectedItem);
$log.info('Item changed to ' + item.route_from_to);
}
}
$scope.init();
});
The problem was caused by angular-material 0.8.3. Updating to the latest release fixed it.
change attribute:
placeholder="Search for a route"
to
md-floating-label="Search for a route"

Angular Material - Dynamically add tab and change to that tab

Currently working on a chat app here https://playwithfire.firebaseapp.com/ and whenever a user adds a new room I want the new room tab to be entered. Currently you can add a room but need to click it afterwards to enter that room and display its content.
I tried changing the attribute md-selected="selectedIndex" but that makes no tab active so no content appears.
Is it possible to do what I'm asking for? What I've got so far:
index.html
<div layout="column" ng-controller="RoomController">
<!-- Tabs Container -->
<md-tabs md-stretch-tabs md-selected="selectedIndex">
<!-- Individual Tab -->
<md-tab ng-repeat="room in roomList"
label="{{room.roomName}}">
<div ng-controller="ChatController">
<!-- Display messages -->
<md-list>
<md-item ng-repeat="msg in messages">
<md-item-content>
<div class="md-tile-content">
<div class="bubble">
<strong>{{msg.from}}</strong><br>
{{msg.body}}
</div>
</div>
</md-item-content>
</md-item>
</md-list><!--/DisplayMessages-->
<!-- Chat controls -->
<div layout="row" layout-margin layout-wrap>
<div flex="33">
<!-- Assign username -->
<label for="nameInput">Username</label>
<input ng-model="name" type="text" id="nameInput" placeholder="Enter a username...">
</div>
<div flex="95">
<!-- Post a message -->
<label>Message</label>
<textarea class="form-control"
ng-model="msg"
ng-keydown="addMessage($event)"
id="messageInput"
placeholder="Type a message...">
</textarea>
</div>
<div layout="row" layout-sm="column" layout-margin layout-fill layout-align="start end">
<!-- Click to send message -->
<div flex>
<md-button class="md-raised md-primary pull-left" ng-click="sendMessage()">Send</md-button>
</div>
<!-- Modal to add or join room -->
<div flex ng-controller="ModalController">
<md-button class="md-raised md-primary pull-left" ng-click="open()">Add or Join Room</md-button>
</div>
<!-- Opens helper -->
<div flex ng-controller="HelpController">
<md-button class="pull-right" ng-click="open()" ng-href="">Need help?</md-button>
</div>
</div>
</div><!--/ChatController-->
</md-tab>
</md-tabs><!--/tabs container-->
</div><!--/RoomController-->
room.js
angular.module('myApp')
.controller('RoomController', function($scope, ShareFactory) {
$scope.roomList = ShareFactory.roomList;
// use this to default to index 0 in roomList
$scope.selectedIndex = 0;
$scope.$on('RoomChange', function(event, data) {
$scope.selectedIndex = data;
console.log('Heard the change!');
console.log('The data is: ' + data);
});
});
modal.js
angular.module('myApp')
.controller('ModalController', function($rootScope, $scope, $modal, ChatFactory, ShareFactory) {
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'views/modal.html',
controller: 'ModalInstanceController'
});
modalInstance.result.then(function (name) {
var found = false;
var length = ShareFactory.roomList.length;
var index = 0;
for(var i = 0; i < length; ++i) {
if(ShareFactory.roomList[i].roomName === name) {
found = true;
index = i;
console.log('index ' + index);
}
}
if(!found) {
ShareFactory.roomList.push({ roomName : name});
index = ShareFactory.roomList.length - 1;
}
else {
// don't care about disabled, not a feature i want to use
//ShareFactory.roomList[index].disabled = false;
}
// Broadcast event to all children of rootScope
// namely want RoomController to listen for this change
$rootScope.$broadcast('RoomChange', index);
}, function () {
console.log('cancel');
});
};
});
Ya know, this definitely came up in a Github issue a while ago, but it may have been kicked to the backlog due to other high priority issues.
I just added this feature to master:
https://github.com/angular/material/commit/8285e2d0bb6efbc72e311ee85b619cbbe8437072
And it should be viewable shortly on our site in the second demo:
https://material.angularjs.org/HEAD/#/demo/material.components.tabs
In the meantime, you should be able to solve this by adding the following code:
if(!found) {
ShareFactory.roomList.push({ roomName : name});
index = ShareFactory.roomList.length - 1;
$timeout(function () {
ShareFactory.selectedIndex = index;
});
}
The $timeout is necessary because you must wait until after the render is finished before you can update the selected index to the new one - otherwise, it will think that the valid is out of range.
Hope this helps!

Resources