ng-if inside of md-menu not opening properly - angularjs

I have an ng-if inside of an <md-menu> tag that toggles more info when the user clicks on the item in the menu. However, when I click on the menu item, the menu closes. When I reopen it, the DOM displays that the extra info is showing but it is not actually being displayed in the menu and the menu has not resized to fit what should be there.
Here is my menu code:
<md-menu>
<md-button aria-label="Open Notifications Menu" ng-click="$mdOpenMenu($event)">
<md-icon md-svg-icon="bell"></md-icon>
</md-button>
<md-menu-content width="5">
<md-menu-item ng-repeat="notification in vm.notificationList">
<div aria-label="Notification" ng-click="vm.showDetails(notification)" md-prevent-menu-close="md-prevent-menu-close">
<div layout="column">
<div flex layout="row" layout-align="start center">
<span flex><b>{{notification.title}}</b></span>
<span style="opacity: 0.5">{{vm.getTime(notification)}}</span>
</div>
<div ng-show="notification.showDetails">
<span style="opacity: 0.7">{{notification.details}}</span>
</div>
</div>
</div>
</md-menu-item>
</md-menu-content>
</md-menu>
Here is the function for the ng-click in typescript:
showDetails(message: any): void {
message.showDetails = !message.showDetails;
}
EDIT
I fixed the problem with the menu closing using md-prevent-menu-close... duh. I've updated the html. The problem is still the same though, the menu does not change size to display the new data.
EDIT
I fixed the problem with the content not showing by removing the md-button and replacing it with a div. I updated the html accordingly. The only problem now is that the menu will not adjust its height to fit the new content neatly.

Is this the kind of thing that you want? - CodePen
Markup
<div ng-controller="AppCtrl as vm" ng-cloak="" ng-app="MyApp">
<md-menu>
<md-button aria-label="Open Notifications Menu" ng-click="$mdOpenMenu($event)">
Bell
</md-button>
<md-menu-content width="5">
<md-menu-item ng-repeat="notification in vm.notificationList" ng-click="vm.showDetails($index)" md-prevent-menu-close="md-prevent-menu-close" aria-label="Notification">
<div layout="column" flex>
<div flex layout="row" layout-align="start center">
<span flex><b>{{notification.title}}</b></span>
<span style="opacity: 0.5">22-08-2016 09:06</span>
</div>
<div ng-if="notification.showDetails">
<span style="opacity: 0.7">{{notification.details}}</span>
</div>
</div>
</md-menu-item>
</md-menu-content>
</md-menu>
</div>
JS
angular.module('MyApp',['ngMaterial', 'ngMessages'])
.controller('AppCtrl', function() {
var vm = this;
vm.notificationList = [
{title: "Read", details: "Enjoy the book", showDetails: false},
{title: "Eat", details: "You're hungry", showDetails: false},
{title: "Dring", details: "Have a pint of lager", showDetails: false}
]
vm.showDetails = function (index) {
vm.notificationList[index].showDetails = !vm.notificationList[index].showDetails;
}
});

Use ng-show not ng-if. ng-if removes elements from the DOM permanently if some condition is no satisfied. ng-show just toggles between whether or not an element is hidden.

Related

How to create a popup element to be over md-dialog?

I'm using AngularJs 1.7, and i've created a dropdown element that i want to add it to md-dialog, the problem is that my element (my-popup) always remains in the limits of the md-dialog - like in here
I want to achieve the same behaviour of the date-picker - as you can see - it's appears in the correct place and over the md-dialog - i wonder how it can done.
I've tried to append the popup to the body , but this way messed up the position of the popup - i guess there is a better way.
$scope.open = function(){
$scope.isShowMyPopUp = !$scope.isShowMyPopUp;
if(!!$scope.isShowMyPopUp){
let modalContainer = $('#myPopUp');
modalContainer.detach();
modalContainer.appendTo('body');
}
Here is the Example
You need to put your "myPopUp" div inside the dialog-content directly and modify your css like the following
HTML :
<md-dialog aria-label="Mango (Fruit)" class="mango-dialog">
<form ng-cloak>
<md-toolbar>
<div class="md-toolbar-tools">
<h2>Mango (Fruit)</h2>
<span flex></span>
<md-button class="md-icon-button" ng-click="cancel()">
<md-icon md-svg-src="img/icons/ic_close_24px.svg" aria-label="Close dialog"></md-icon>
</md-button>
</div>
</md-toolbar>
<md-dialog-content>
<div class="my-popup" ng-show="isShowMyPopUp" id-"myPopUp">
<div ng-repeat="item in daySelect">
<md-button class="md-raised md-primary" ng-class="{'selected':item.isSelected}" ng-click="select(item)"> {{item.text}}</md-button>
</div>
</div>
<div class="md-dialog-content">
<div layout-gt-xs="row">
<div flex-gt-xs>
<h4>Standard date-picker</h4>
<md-datepicker ng-model="ctrl.myDate" md-placeholder="Enter date"></md-datepicker>
</div>
<div flex-gt-xs style="position:relative;">
<h4>my-popup</h4>
<md-button class="md-raised md-primary" ng-click="open()">Open</md-button>
</div>
</div>
</div>
</md-dialog-content>
</form>
</md-dialog>
CSS :
.my-popup{
position:absolute;
top: 48px;
left: 104px;
width:250px;
height:250px;
background-color:gray;
z-index: 999;
overflow: auto;
}
md-dialog{
width:40%;
}
.selected {
background-color:green!important;
}
.mango-dialog {
overflow: visible;
}
I added mango-dialog class to your dialog to allow overflow , also I added z-index to the pop up to make sure it is on top
here is a working example

Why my leftsideBar doesn't work? in angular material

I want to make sidenav with angular material.
<div class="example-tabs-500-height elements-sidebar-example ">test1<!-- right sidebar -->
<section layout="row" flex>
<md-sidenav class="md-sidenav-left" md-component-id="left"
md-disable-backdrop md-whiteframe="4">
<md-toolbar class="md-theme-indigo">
<h1 class="md-toolbar-tools">Disabled Backdrop</h1>
</md-toolbar>
<md-content layout-margin>
<p>
This sidenav is not showing any backdrop, where users can click on it, to close the sidenav.
</p>
</md-content>
</md-sidenav>
<md-content flex layout-padding>
<div layout="column" layout-align="top center">
<p>
Developers can also disable the backdrop of the sidenav.<br/>
This will disable the functionality to click outside to close the sidenav.
</p>
<div>
<md-button ng-click='toggleLeft("left")' class="md-raised">
Toggle Sidenavs
</md-button>
</div>
</div>
</md-content>
</section>
and in controller:
$scope.toggleLeft = toggleLeft;
// $scope.toggleRight = buildToggler('right');
function toggleLeft(componentId) {
console.log('toogle');
return function() {
$mdSidenav(componentId).toggle();
}
}
Function toggleLeft writes in console 'toogle'.
Why are you returning a function?
function() {
$mdSidenav(componentId).toggle();
}
Shou be only:
function toggleLeft(componentId) {
console.log('toogle');
$mdSidenav(componentId).toggle();
}
UPDATE
Take a look on this example: http://codepen.io/anon/pen/pEJOzg

Angular Material - md-radio-group not rendering as expecting safari

I have a multi row of radio buttons through a ng-repeat. In Safari the radio buttons render overlapping each other. A photo of the behaviour below:
In Chrome it renders as expected photo below.
[
What I am doing wrong? Code below:
<div ng-repeat="item in multi.multiChoice" layout="column" layout-align='start start' ng-if="multi.viewFn()">
<div class='multi-button' flex='70' md-theme="altTheme">
<md-radio-group class='md-primary' ng-model="multi.content.value" >
<div flex layout='row' layout-padding layout-align="start center" ng-style="{'background-color':multi.checkFn('BG',item.value),'color':multi.checkFn('FONT',item.value)}">
<md-radio-button flex ng-value="item.value">
{{item.value}}
</md-radio-button>
</div>
<span </span>
</md-radio-group>
</div>
</div>
<md-button class="md-raised md-warn" aria-label="Edit" ng-click="multi.content.value=null" ng-if="multi.viewFn()">
Clear
</md-button>
<label ng-if="!multi.viewFn()">{{multi.content.value}}</label>
You need to move the ng-repeat from the outermost div to the parent div of the md-radio-button - CodePen
Markup
<div ng-controller="AppCtrl" ng-cloak="" ng-app="MyApp">
<md-radio-group class='md-primary' ng-model="multi.content.value" >
<div flex layout='row' layout-padding layout-align="start center" ng-style="{'background-color':multi.checkFn('BG',item.value),'color':multi.checkFn('FONT',item.value)}" ng-repeat="item in multi.multiChoice">
<md-radio-button flex ng-value="item.value">{{item.value}}</md-radio-button>
</div>
</md-radio-group>
<md-button class="md-raised md-warn" aria-label="Edit" ng-click="multi.content.value=null">
Clear
</md-button>
<label>{{multi.content.value}}</label>
</div>
JS
.controller('AppCtrl', function($scope) {
$scope.multi = {
multiChoice: [
{value: "Tom Cruise"},
{value: "Danny De Vito"},
{value: "Hugh jackman"}
]
}
});

Using a slide-out menu for each tab in <md-tabs>

I want to built a slide out menu for my application using angular material.
I have certain tabs, each of which will have a slide-out menu with different content. I have implemented this in the following manner:
<md-tab ng-repeat="tab in categories"
ng-disabled="tab.disabled"
label="{{tab.title}}"
md-on-select="setArray(tab.title,0)">
<!--Include a dropdown of sub-categories here -->
<div layout="row">
<md-menu id="sub-cat-button">
<md-button ng-click="$mdOpenMenu($event)" class="md-icon-button" aria-label="Open sample menu">
<span class="glyphicon glyphicon-menu-down" aria-hidden="true"></span>
</md-button>
<md-menu-content width=6>
<md-menu-item ng-repeat="sub_cat in tab.sub_cat">
<md-button ng-click="setArray(sub_cat,1)">{{sub_cat}}</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
<ol class="breadcrumb" id="breadcrumb">
<li ng-repeat="link in bread">{{link}}</li>
</ol>
<md-sidenav md-component-id="right" class="md-sidenav-right">
<md-button ng-click="openRightMenu()">
<i class="material-icons">keyboard_arrow_right</i>
</md-button>
</md-sidenav>
<md-content>
<md-button ng-click="openRightMenu()">
<span class="glyphicon glyphicon-filter" aria-hidden="true"></span>
</md-button>
</md-content>
</div>
<div class="demo-tab tab{{$index%4}}" id="scrollable-tabs">
<div class="row" infinite-scroll="loadMore()" infinite-scroll-disabled="busy">
<div ng-repeat="p in products">
<h3><div class="well">{{p.id}}</div></h3>
</div>
</div>
<div ng-show="busy">Loading more products....</div>
<br/>
</div>
</md-tab>
The problem here is that, the menu slides out and can be seen only for tab 1. If I go to tab 5 and click on the filter button to open that menu, the menu is not seen slid out with tab 6 , but it has been already slid out for tab 1. you can view it slide out when you go to tab 1.
How do I make it visible for each tab, because the content of the slide out menu is dependent on the tab which is opened?

How to get a full height sidenav with Angular-Material

I am using Angular-Material and have implemented a SideNav menu. When the screen size is small, the menu is hidden and when click on the Menu toggle button, the menu slides out from the left, with a full page height. When the screen is larger, the menu appears fixed to the left side, but not at full page height.
How can i make the fixed menu appear to be full page height.
I have been playing with the css and other md attributes, but just can't find out how.
<div ng-controller="appCtrl" layout="vertical" layout-fill>
<md-toolbar class="md.medium-tall app-toolbar">
<div class="md-toolbar-tools" ng-click="toggleMenu()">
<button class="menu-icon" hide-sm aria-label="Toggle Menu">
<md-icon icon="img/icons/ic_menu_24px.svg">
<object class="md-icon" data="img/icons/ic_menu_24px.svg"></object>
</md-icon>
</button>
<h2>
<span>Dev.Material</span>
</h2>
</div>
</md-toolbar>
<section layout="horizontal" flex>
<md-sidenav class="md-sidenav-left md-whiteframe-z2" component-id="menu" is-locked-open="$media('sm')">
<md-toolbar md-theme="purple">
<h1 class="md-toolbar-tools">Sidenav Left</h1>
</md-toolbar>
<md-content class="md-padding" ng-controller="menuCtrl">
<p>
This sidenav is locked open on your device. To go back to the default behavior,
narrow your display.
</p>
</md-content>
</md-sidenav>
<md-content flex class="md-padding">
Some content !!
</md-content>
and the controller:
(function () {
'use strict';
var controllerId = 'appCtrl';
angular.module('app').controller(controllerId,
['$scope', '$timeout', '$mdSidenav', appCtrl]);
function appCtrl($scope, $timeout, $mdSidenav) {
var vm = this;
$scope.toggleMenu = function() {
$mdSidenav('menu').toggle();
};
};
})();
(function () {
'use strict';
var controllerId = 'menuCtrl';
angular.module('app').controller(controllerId,
['$scope', '$timeout', '$mdSidenav', menuCtrl]);
function menuCtrl($scope, $timeout, $mdSidenav) {
var vm = this;
$scope.close = function() {
$mdSidenav('menu').close();
};
};
})();
I had the exact same issue with angular-material 0.6.0 rc1. (I used the code from the demo site).
The problem does not come from the angular-material code, but from the parent css container of your page which is not full height.
Your page should have a structure like :
<ui-view class="ng-scope">
<div ng-controller="appCtrl" layout="vertical" layout-fill>
... your md sidenav code here ...
</div>
</ui-view>
The issue comes from the ng-scope class wich is not full height. In my case I just copy / past the code from the demo site and add this im my cutom css file
.ng-scope { height: 100%; }
The result is a full height sidenav working fine in both locked-open and unlock mode.
This worked for me...
1) Wrap your sidenav in a div that has a layout="vertical" like so...
<div ng-include="'scripts/shared/sidenav/sidenav.html'" layout="vertical"></div>
2) Add "flex" in your sidenav so that it will flex to fill out the full page height.
<md-sidenav class="md-sidenav-left md-whiteframe-z2" component-id="menu" is-locked-open="$mdMedia('sm')" flex>
I fixed this same issue by adding a class to my sidenav with
position: fixed;
I had a similar Problem. Setting style"height: 100vh;" worked for me.You can also use a class.
<div layout="column" style="height:100vh;"></div>
layout="vertical" can also be used - it doesn't have any significant effect in my context.
Try adding layout-fill attribute on main md-content tag that has ui-view attribute set.
<md-content ui-view layout-fill layout-align="center center">
</md-content>
You need to use flex in both the sidebar and content, as well as in the top container. This way you don't need to use any additional styles.
Here is your code working correctly (note that I updated some parts to the latest Angular Material version):
<div ng-controller="appCtrl" layout="column" flex>
<md-toolbar class="md.medium-tall app-toolbar">
<div class="md-toolbar-tools" ng-click="toggleMenu()">
<button class="menu-icon" hide-sm aria-label="Toggle Menu">
<md-icon icon="img/icons/ic_menu_24px.svg">
<object class="md-icon" data="img/icons/ic_menu_24px.svg"></object>
</md-icon>
</button>
<h2>
<span>Dev.Material</span>
</h2>
</div>
</md-toolbar>
<section layout="row" flex>
<md-sidenav flex class="md-sidenav-left md-whiteframe-z2" md-component-id="left" md-is-locked-open="$mdMedia('gt-sm')">
<md-toolbar md-theme="purple">
<h1 class="md-toolbar-tools">Sidenav Left</h1>
</md-toolbar>
<md-content class="md-padding" ng-controller="menuCtrl">
<p>
This sidenav is locked open on your device. To go back to the default behavior,
narrow your display.
</p>
</md-content>
</md-sidenav>
<md-content flex class="md-padding">
Some content !!
</md-content>
</section>
</div>
Just create a sidenav outside a <div>. For example, just after the <body> tag, you could write:
<body layout="row">
<md-sidenav class="md-sidenav-left md-whiteframe-z2" md-component-id="left" md-is-locked-open="$media('gt-md')">
<md-toolbar md-theme="deep-orange">
<h2 class="md-toolbar-tools">Menu</h2>
</md-toolbar>
<md-content ng-controller="menuBar" md-theme="deep-orange">
<md-button layout-align="left" ng-repeat="item in items" ui-sref="{{item.location}}" class="menu-item"
md-ink-ripple="#bbb" aria-hidden="false">
<!-- the above <md-button> just repeats buttons created in the JS -->
<span>{{item.label}}</span>
</md-button>
</md-content>
</md-sidenav>
<!-- Other content ... -->
</body>
This code will give you a fully vertical sidebar.
None of the above worked for me for the angular material ver: 1.1.0-RC.5, so I did it like this :
<body layout="column">
<div layout="row" ng-controller="reviewController" ng-cloak flex>
<div layout="row">
<md-sidenav class="md-sidenav-left" md-component-id="left" md-is-locked-open="$mdMedia('gt-sm')" md-whiteframe="4" layout="column">
<md-toolbar class="md-theme-indigo" class="md-medium-tall">
<h1 class="md-toolbar-tools">Sidenav Left</h1>
</md-toolbar>
<div ng-controller="LeftCtrl">
<md-button ng-click="close()" class="md-primary" hide-gt-sm>
Close Sidenav Left
</md-button>
<p hide show-gt-sm flex>
This sidenav is locked open on your device. To go back to the default behavior, narrow your display.
</p>
<p flex>
hi
</p>
<p flex>
there!
</p>
</div>
</md-sidenav>
<div layout-column flex>
<p flex>
The left sidenav will 'lock open' on a medium (>=960px wide) device.
</p>
<p flex>
The right sidenav will focus on a specific child element.
</p>
<div flex>
<md-button ng-click="toggleLeft()" class="md-primary" hide-gt-sm>
Toggle left
</md-button>
</div>
<div flex>
<md-button ng-click="toggleRight()" ng-hide="isOpenRight()" class="md-primary">
Toggle right
</md-button>
</div>
<md-content ui-view layout="column" flex></md-content>
</div>
<md-sidenav class="md-sidenav-right md-whiteframe-4dp" md-component-id="right">
<md-toolbar class="md-theme-light">
<h1 class="md-toolbar-tools">Sidenav Right</h1>
</md-toolbar>
<md-content ng-controller="RightCtrl" layout-padding>
<form>
<md-input-container>
<label for="testInput">Test input</label>
<input type="text" id="testInput" ng-model="data" md-autofocus>
</md-input-container>
</form>
<md-button ng-click="close()" class="md-primary">
Close Sidenav Right
</md-button>
</md-content>
</md-sidenav>
</div>
</div>
The above code is almost same as that given in the angular material docs and the Js file is also similar to that given in docs :)
EDIT:
More references:
1. https://gist.github.com/epelc/6aa345f4496776569830. Correct the depreciated value of $media('gt-lg') to $mdMedia('gt-sm')
2. https://github.com/angular/material/issues/1092
The above issue was resolved only by modifying css and no need to change any code at all.
Solution-
.ng-scope { height: 100%; }
<div layout="column" layout-fill>
<section layout="row" flex>
<md-sidenav class="md-sidenav-left"
md-component-id="left"
md-is-locked-open="$mdMedia('gt-md')"
md-disable-backdrop
md-whiteframe="4">
<md-content>
<div layout="row" layout-align="center center">
<md-button ng-click="closeSideNav()" class="md-primary">
Agregar Zona +
</md-button>
</div>
<p hide show-gt-md>
This sidenav is locked open on your device. To go back to the default behavior,
narrow your display.
</p>
</md-content>
</md-sidenav>
</section>
Test
I tried so many things to fix this issue, and I finally was able to fix it by adding the uiview directly to my menu component:
<menu uiview layout="column" class="menu"> </menu>
I didn't try the other fixes with directives but I used this simple css and got what I needed. Any corrections or advice about this css would be welcome.
md-sidenav {
height: -webkit-fill-available;
}

Resources