Change button's theme when sidenav toggles (angular-material) - javascript

I'm making a website using angular-material. There is a sidenav and a button. Whenever the sidenav toggles, I want the button to changes it's theme. Like, when the sidenav is open, the button's md-theme attribute is set to "cyan" and when sidenav is close, the button is set to another theme.
My html code:
<div ng-app="app" ng-controller="navCtrl" layout="column">
<section layout="row" flex>
<md-content flex class="md-padding">
<div layout="column" layout-fill layout-align="center center">
<md-button class="md-fab md-primary" md-theme="cyan" ng-click="toggle()" aria-lebel="Navicon">
<md-icon class=""></md-icon>
</md-button>
</div>
</md-content>
<md-sidenav class="md-sidenav-left" md-component-id="nav"></md-sidenav>
</section>
</div>
And my controller:
angular.module('app', ['ngMaterial'])
.controller('navCtrl', function($scope, $timeout, $mdSidenav) {
$scope.toggle = function() {
$mdSidenav('nav').toggle();
};
});
I couldn't find a way to listen to this toggling and change the theme.

The directive supports a md-is-open attribute that identifies a $scope or controller attribute value that is updated when the sidenav state is changed ( open <-> closed ).
Then, the $mdSidenav('nav').toggle() function returns a promise, so define the 'then' to set a 'theme' attribute in your controller that is referenced from the md-theme in your side-nav markup:
<md-button class="md-fab md-primary"
ng-click="toggle()" aria-label="Navicon"
md-theme="buttonTheme" >
...
<md-sidenav class="md-sidenav-left" md-component-id="nav"
md-is-open="isOpen"></md-sidenav>
...
angular.module('app', ['ngMaterial'])
.controller('navCtrl', function($scope, $timeout, $mdSidenav) {
$scope.isOpen = false;
$scope.buttonTheme = 'cyan';
$scope.toggle = function() {
$mdSidenav('nav').toggle().then( function() {
$scope.buttonTheme = ($scope.isOpen ? 'indigo' : 'cyan');
});
};
});

Related

Scroll to bottom when new md-list-item is added to the md-list Angular Material

I'm implementing a chat using Angular and Angular Material and Im stuck at making the md-list scroll at the very bottom when i modify the model with new message in messages array. Tried many things but with no success watchCollection is working but i cant seem to find the way to scroll to the md-list at the very bottom. Maybe its something with the material
HTML:
<md-content flex layout-padding>
<md-list flex scroll-bottom="vm.messages">
<md-list-item class="md-3-line" ng-repeat="msg in vm.messages">
<!--<img ng-src="{{user.userAvatar}}" class="md-avatar" alt="{{user.userName}} Avatar"/>-->
<div class="md-list-item-text" layout="row">
<div flex="15"></div>
<div flex="70" layout="column">
<h3>{{msg.text}}</h3>
</div>
<div flex></div>
</div>
</md-list-item>
</md-list>
</md-content>
Angular Directive:
angular.module('chat').directive('scrollBottom', function ($timeout) {
return {
restrict: 'A',
scope: {
scrollBottom: "<"
},
link: function (scope, element) {
scope.$watchCollection('scrollBottom', function (newValue) {
if (newValue)
{
element.scrollTop = element.scrollHeight;
}
});
}
}
})
As I post in a comment, and taking this SO question as reference,
the key here is adding your scrollBottom directive to md-content element instead of md-list.

Angular material $mdDialog with second place holder

I am trying to add a second input to an angular material dialog, but I am not sure if it is possible. I tried to add the Test2 placeholder but didn't work. Thank you for the help in advance.
$scope.showPrompt = function (ev) {
$scope.statusTopic = '';
var confirm = $mdDialog.prompt()
.title('Test?')
.placeholder('Test1')
//.placeholder('Test2')
.targetEvent(ev)
.ok('Okay!')
.cancel('Cancel');
Here's an example using Custom Dialog - CodePen
Markup
<div ng-controller="MyController as vm" ng-cloak="" ng-app="app">
<md-button class="md-primary md-raised" ng-click="vm.open($event)">
Custom Dialog
</md-button>
<div ng-if="vm.showText" layout="column">
{{vm.placeholder1}}
<br>
{{vm.placeholder2}}
</div>
<script type="text/ng-template" id="test.html">
<md-dialog aria-label="Test">
<div layout-padding layout="column">
<md-input-container>
<label>Placeholder 1</label>
<input ng-model="vm.placeholder1">
</md-input-container>
<md-input-container>
<label>Placeholder 2</label>
<input ng-model="vm.placeholder2">
</md-input-container>
<md-button ng-click="vm.save()" class="md-primary">Save</md-button>
</div>
</md-dialog>
</script>
</div>
JS
angular.module('app',['ngMaterial'])
.controller('MyController', function($scope, $mdDialog) {
this.open = function(ev) {
this.showText = false;
$mdDialog.show(
{
templateUrl: "test.html",
clickOutsideToClose: true,
scope: $scope,
preserveScope: true,
controller: function($scope) {
},
});
};
this.save = function () {
this.showText = true;
$mdDialog.cancel();
}
})
Demo:
https://material.angularjs.org/latest/demo/input
Docs:
https://material.angularjs.org/latest/api/directive/mdDialog
https://material.angularjs.org/latest/api/service/$mdDialog

Problems with implementing separate controller for each md-tab

My template HTML file 'testview.html' looks like this:
<div class="container-fluid">
<md-toolbar>
<h2 class="md-toolbar-tools">
<span>Test View</span>
</h2>
</md-toolbar>
<md-tabs md-stretch-tabs
md-selected="selectedIndex">
<md-tab label="basicConfig">
</md-tab>
<md-tab label="awardSettings">
</md-tab>
</md-tabs>
<div id="content" ui-view flex> </div>
</div>
This is my route controller 'testview.js':
angular
.module('app.testview')
.controller('TestView', TestView)
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('basicConfig', {
url: '/basicConfig',
templateUrl: 'app/testview/testview_partials/basicConfig.html',
controller: 'BasicConfig as vm'
})
.state('awardSettings', {
url: '/awardSettings',
templateUrl: 'app/testview/testview_partials/awardSettings.html',
controller: 'AwardSettings as vm'
})
}]);
TestView.$inject = ['$state', '$scope', '$location'];
function TestView(state, $scope, $location) {
$scope.selectedIndex = -1;
$scope.$watch('selectedIndex', function(current, old) {
switch (current) {
case 0:
$location.url("/basicConfig");
break;
case 1:
$location.url("/awardSettings");
break;
}
});
}
Here's what my awardSettings.html looks like:
<form name="awardSettingsForm" id="awardSettingsForm">
<md-content flex layout-padding layout="row" layout-sm="column" layout-align-sm="space-between start" layout-align="space-between center">
<label style="font-size: 24px;">Award Settings</label>
</md-content>
</form>
I have my basicConfig & awardSettings html & controllers defined in separate files. I know that my routes are working correctly. But my problem is that I want the contents of basicConfig.html & awardSettings.html within their tabs. But that's not working. IT looks like below when I click on the tab
Any help would be appreciated. Thanks!
Never mind. I figured out what I was doing wrong. Had to change sub states to be part of the main state ie. change state from 'basicConfig' to 'testview.basicConfig'.
function stateConfig ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('testview.basicConfig', {
templateURL: 'app/testview/testview_partials/basicConfig.html',
controller: 'BasicConfig'
})
.state('testview.awardSettings', {
template: '<h3>Award!!</h3>',
controller: 'AwardSettings'
})
}

TypeError: $translate.use is not a function

So i first added the languages en, fr & nl to my app.js file. This is horrible bad practice so i now got the translations out of the app.js file and pasted them in JSON formatted files.
However, when i load the site now, in my controller the changeLanguage method is causing a TypeError: $translate.use is not a function. Does anyone see my mistake?
(FIRST THE CODE)
app.js:
var app = angular.module('eva', ['ui.router', 'ngMaterial', 'ngMessages',
'controllers', 'factories', 'ngAnimate', '720kb.socialshare',
'angular-loading-bar', 'angular-svg-round-progress', 'pascalprecht.translate', 'ngSanitize',
'facebook']);
app.config(function ($translateProvider) {
$translateProvider.useSanitizeValueStrategy('sanitize');
$translateProvider.useStaticFilesLoader({
prefix: '../languages/',
suffix: '.json'
});
$translateProvider.registerAvailableLanguageKeys(['en', 'nl', 'fr'], {
'en': 'en',
'nl': 'nl',
'fr': 'fr'
});
$translateProvider.preferredLanguage('nl');
});
index.html:
<body layout="column" ng-controller="AppCtrl" layout-fill>
<div id="fb-root"></div>
<!--<vid-bg resources="resources" class="video" poster="poster" full-screen="fullScreen" muted="muted" z-index="zIndex" play-info="playInfo" pause-play="pausePlay"></vid-bg>-->
<!-- ANGULAR MATERIAL LOADING -->
<md-toolbar layout="row" md-scroll-shrink ng-if="true">
<div class="md-toolbar-tools ng-scope" ng-controller="NavCtrl as demo">
<md-button ng-click="toggleSidenav('left')" class="md-icon-button" ng-show="isLoggedIn()" aria-haspopup="true" aria-expanded="true"
aria-label="sidebar menu">
<md-icon aria-label="Menu" md-svg-icon="./js/lib/material-design-icons/navigation/svg/design/ic_menu_24px.svg"></md-icon>
<md-tooltip md-direction="bottom">{{ 'MENU' | translate }}</md-tooltip>
</md-button>
<span>
<md-button md-no-ink href="#/index" aria-label="logo">
<img src="js/lib/images/logo/48x48.png" alt="logo" >
</md-button>
</span>
<!-- fill up the space between left and right area -->
<span flex></span>
<md-fab-speed-dial md-direction="left" ng-class="demo.selectedMode">
<md-fab-trigger>
<md-button aria-label="menu" class="md-fab md-warn">
<md-tooltip md-direction="bottom">Menu</md-tooltip>
<md-icon aria-label="Menu" md-svg-icon="./js/lib/material-design-icons/action/svg/design/ic_language_24px.svg"></md-icon>
</md-button>
</md-fab-trigger>
<md-fab-actions>
<md-button aria-label="dutch" class="md-fab md-raised md-mini" ng-click="changeLanguage('nl')">
<md-tooltip md-direction="bottom">Dutch</md-tooltip>
<p>nl</p>
</md-button>
<md-button aria-label="english" class="md-fab md-raised md-mini" ng-click="changeLanguage('en')">
<md-tooltip md-direction="bottom">English</md-tooltip>
<p>en</p>
</md-button>
<md-button aria-label="french" class="md-fab md-raised md-mini" ng-click="changeLanguage('fr')">
<md-tooltip md-direction="bottom">French</md-tooltip>
<p>fr</p>
</md-button>
</md-fab-actions>
</md-fab-speed-dial>
</div>
</md-toolbar>
appController:
angular.module('controllers')
.controller('AppCtrl', ['$scope', '$mdSidenav',
'$mdToast','$translate', 'auth', 'Facebook','$state', function($scope, $mdSidenav, $translate, auth, Facebook,$state){
/* sidenav togglen */
$scope.toggleSidenav = function(menuId) {
$mdSidenav(menuId).toggle();
};
/* taal veranderen */
$scope.changeLanguage = function(langKey){
$translate.use(langKey);
$state.reload();
};
The ERROR happens at the $translate.use(langKey); line of the code piece above.
Here you can see my JSON file structure: http://imgur.com/xNo2MxX.
And this is an example of my JSON language file: http://imgur.com/9TB8FX1.
Here's how the site looks: http://imgur.com/pEyo1YN.
If there's any ) or ; or similar missing at the end of the code "snippets" it's because i copy pasted only parts of a page, the parts that matter so don't worry they're all there.
Anyone can see what causes the error?
Fixed, in my modules i forgot $mdToast ... they have to all be loaded AND in the same order.

How to access controller of the current view in ion-header-bar which is saved as a directive?

When I put my ion-header-bar in a seperate file (header-dash.html) and assign it as a directive "headerDash", I seem not to be able to access my DashCtrl or the controller of my view where the header-dash directive is called. More specific, in the code below, I cannot call the function changeDashMode(). However, when I replace <header-dash></header-cash> with the content of header-dash.html, then everything works fine.
I guess it has something to do with the setup of the directive, anyone thoughts?
Update: newImport() also in header-dash does work... it is when I added another function changeDashMode that it does not work. What is going on?
controllers.js
.controller('DashCtrl', function($scope) {
// -------------------------------------------------------------------------
// Init
$scope.dashMode = false;
// ---------------------------------------------------------------------------
$scope.changeDashMode = function() {
console.log("test")
if (!$scope.dashMode) {$scope.dashMode = true;} else {$scope.dashMode = false;}
}
// and the rest of the controller
// ...
})
header-dash.html
<ion-header-bar align-title="center" class="bar-positive">
<div class="buttons">
<button class="button button-light" ng-click="newImport()">+ New</button>
</div>
<h1 class="title"><logo></logo></h1>
<div class="buttons" ng-controller="DashCtrl">
<button class="button button-light" ng-show="!dashMode" ng-click="changeDashMode()">Select</button>
<button class="button button-light" ng-show="dashMode" ng-click="changeDashMode()">Edit</button>
</div>
</ion-header-bar>
tab-dash.html
<ion-view view-title="Dashboard">
<header-dash></header-dash>
<ion-content has-bouncing="true" has-header="true">
<ion-refresher
pulling-text="Pull to refresh..."
on-refresh="doRefresh()">
</ion-refresher>
<ion-list>
<ion-item>Select mode? {{dashMode}}</ion-item>
</ion-list>
</ion-content>
</ion-view>
directives.js
angular.module('starter.directives', [])
.directive('headerDash', function() {
return {
restrict: 'E',
templateUrl: 'templates/header-dash.html' // tried to add controller: "DashCtrl" but that didnt work
}
})
Is tab-dash.html being the template displayed by the DashCtrl?
Because in header-dash.html, you're using ng-controller again, creating an child scope, effectively having DashCtrl in DashCtrl
<div class="buttons" ng-controller="DashCtrl">

Categories

Resources