Daniel Kobe Daniel Kobe - 4 months ago 91
Javascript Question

Angular Material $mdDialog does not show after hiding once

My app has a chat button which opens an

$mdDialog
. I use
$mdDialog.hide()
to close the dialog window when a user name is clicked in the dialog window. This works but when I click on the chat button again, it no longer works.

Thanks for any help. Heres a link to my codepen.

HTML



<div ng-app="MyApp" ng-controller="AppCtrl">
<div id="menubar">
<div class="logo"><a href="#"><img src="http://i.imgur.com/yS9Ug9Z.png"/></a></div>
<ul class="middle">
<div class="r1">Project Name <i class="glyphicon glyphicon-pencil"></i></div>
<ul class="r2">
<li class="dropdown">
<button href="#" data-toggle="dropdown" class="dropdown-btn">File</button>
<ul class="dropdown-menu">
<li><a href="#">Action 1</a></li>
<li><a href="#">Action 2</a></li>
<li><a href="#">Action 3</a></li>
</ul>
</li>
<li class="dropdown">
<button href="#" data-toggle="dropdown" class="dropdown-btn">Edit</button>
<ul class="dropdown-menu">
<li><a href="#">Action 1</a></li>
<li><a href="#">Action 2</a></li>
<li><a href="#">Action 3</a></li>
</ul>
</li>
<li class="dropdown">
<button href="#" data-toggle="dropdown" class="dropdown-btn">Help</button>
<ul class="dropdown-menu">
<li><a href="#">Action 1</a></li>
<li><a href="#">Action 2</a></li>
<li><a href="#">Action 3</a></li>
</ul>
</li>
</ul>
</ul>
<div class="menu-btns">
<button id="comment-btn"><i class="material-icons">assignment</i> <span>Comment</span></button>
<button id="share-btn"><i class="material-icons">supervisor_account</i> <span>Share</span></button>
<button id="chat-btn" ng-click="openChatDialog()"><i class="material-icons">chat</i> <span>Chat</span></button>
</div>
<button id="user-btn"></button>
<div id="user-drop" class="shadow-1">
<ul>
<li>Smile</li>
<li>You</li>
<li>Goodlookin</li>
<li>Get Shwify</li>
<li>Cellar Door Is Beautiful</li>
<hr/>
<li>Your Profile</li>
<ul class="links">
<li>Link1</li>
<li>Link2</li>
<li>Link3</li>
</ul>
</ul>
</div>
</div>
<div id="chat-cntnr">
<div ng-repeat="chat in chat.openChats" class="chat-box">
<div class="chat-header">
<button ng-click="closeChat()" class="chat-h-btn chat-close"><i class="glyphicon glyphicon-remove"></i></button>
</div>
</div>
</div>
</div>


JS



angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])

.controller('AppCtrl', function($scope, $mdDialog) {

//CHAT
$scope.chat = {};
$scope.chat.openChats = [];
$scope.collaborators = ['Dan', 'Miles', 'Ryan', 'kevin'];

var chatCntnr = document.getElementById('chat-cntnr');

// open a chat box
var isChatOpen = function(user) {
if ($scope.chat.openChats.indexOf(user) < 0) return false;
else return true;
};

$scope.openChat = function(user) {
if (!isChatOpen(user)) {
if (chatCntnr.style.display !== 'flex') {
chatCntnr.style.display = 'flex';
}
$scope.chat.openChats.push(user);
}
$mdDialog.hide();
};

// close a chat box
$scope.closeChat = function(user) {
console.log('hi');
//$scope.chat.openChats.splice($scope.openChats.indexOf(user), 1);
};

// CHAT DIALOG
$scope.openChatDialog = function() {
$mdDialog.show({
scope: $scope,
controller: 'AppCtrl',
template: '<md-button ng-click="openChat(\'everybody\')">Everybody</md-button><md-button ng-repeat="user in collaborators" ng-click="openChat(user)"><svg class="status-light" height="17" width="17"><circle cx="8" cy="8" r="8" fill="lightGreen" /></svg>{{user}}</md-button>',
hasBackdrop: false,
clickOutsideToClose: true,
openFrom: '#chat-btn',
closeTo: '#chat-btn'
})
};
});
// chat dialog
// chat

/**
* MENUBAR
*/
var dropdownBtns = document.querySelectorAll('.middle .dropdown-btn');
var dropdowns = document.querySelectorAll('.middle .dropdown');
var userBtn = document.getElementById('user-btn');
var userDrop = document.getElementById('user-drop');

document.addEventListener('click', (e) => {
if (userDrop.classList.contains('open')) {
userDrop.classList.toggle('open');
}
});

userBtn.addEventListener('click', (e) => {
userDrop.classList.toggle('open');
e.stopPropagation();
})

for (var i = 0; i < dropdownBtns.length; i++) {
(function() {
var dropdownBtn = dropdownBtns[i];
var k = i;
dropdownBtn.addEventListener('mouseover', () => {
var x = isDropOpen();
if (x > -1 && x !== k) {
dropdowns[x].classList.toggle('open');
dropdowns[k].classList.toggle('open');
}
})
})();
}

var isDropOpen = () => {
for (var i = 0; i < dropdowns.length; i++) {
var dropdownClasses = dropdowns[i].classList;
if (dropdownClasses.contains('open')) return i;
}
return -1;
}

/**
* menubar
*/


CSS



html, body {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
html ul, body ul {
padding: 0;
margin: 0;
}

#menubar {
font-family: sans-serif;
background-color: black;
display: flex;
position: relative;
white-space: nowrap;
}
#menubar .logo {
display: flex;
align-items: center;
padding: 10px;
background-color: lightGrey;
}
#menubar .logo img {
height: 40px;
}
#menubar .middle {
padding: 10px;
padding-top: 8px;
padding-bottom: 0px;
color: white;
width: 100%;
position: relative;
font-family: inherit;
margin-left: 8px;
margin-right: 20px;
}
#menubar .middle .r1 {
font-size: 20px;
}
#menubar .middle .r1 i {
position: relative;
top: -1px;
font-size: 12px;
font-weight: 700;
margin-left: 2px;
cursor: pointer;
}
#menubar .middle .r1 i:hover {
color: lightGrey;
}
#menubar .middle .r2 {
margin-top: 2px;
margin-left: -6px;
font-size: 15px;
padding-bottom: 6px;
}
#menubar .middle .r2 li {
display: inline-block;
}
#menubar .middle .dropdown-btn {
position: relative;
outline: 0;
background-color: transparent;
border: none;
cursor: pointer;
padding: 2px 6px;
z-index: 100;
margin: 0 1px;
margin-top: 1px;
}
#menubar .middle .dropdown-btn:hover {
background-color: grey;
}
#menubar .middle .open .dropdown-btn {
background-color: black;
margin: 0 !important;
border: white 1px solid;
border-bottom: none;
}
#menubar .middle .dropdown-menu {
background-color: black;
border: white 1px solid;
border-radius: 0;
margin-top: -1px;
z-index: 10;
}
#menubar .middle .dropdown-menu li {
display: block;
}
#menubar .middle .dropdown-menu a {
color: white;
}
#menubar .middle .dropdown-menu a:hover {
background-color: dodgerBlue;
}
#menubar .menu-btns {
display: flex;
margin: 12px;
margin-right: 0px;
color: white;
right: 0;
}
#menubar .menu-btns button {
outline: 0;
position: relative;
background-color: transparent;
border-radius: 2px;
border: #343436 3px solid;
margin: 0 5px;
padding: 2px 12px;
font-size: 15px;
white-space: nowrap;
}
#menubar .menu-btns button:hover {
background-color: #4d4d50;
}
#menubar .menu-btns button i {
position: relative;
top: 5px;
color: #aeaeae;
}
#menubar .menu-btns button span {
position: relative;
top: -3px;
}

#user-btn {
margin: 10px;
margin-bottom: 8px;
outline: 0;
width: 70px;
background: url("https://www.fillmurray.com/70/92");
border: none;
border-radius: 2px;
}

#chat-btn {
background-color: #343436 !important;
}
#chat-btn:hover {
background-color: #4d4d50 !important;
}

.shadow-1 {
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
transition: all 0.2s ease-in-out;
}

#user-drop {
display: none;
position: absolute;
right: 0;
top: 100%;
background-color: white;
}
#user-drop ul {
list-style-type: none;
padding: 6px 0;
padding-bottom: 2px;
font-size: 15px;
font-weight: 500;
}
#user-drop ul li {
cursor: pointer;
padding: 4px 16px;
padding-right: 38px;
}
#user-drop ul li:hover {
background-color: #e7e7e7;
}
#user-drop ul hr {
margin: 8px 0;
border-top: black 1px solid;
}
#user-drop ul .links {
padding-top: 0;
}
#user-drop ul .links li {
display: inline-block;
padding-right: 2px;
font-size: 11px;
color: darkGrey;
}
#user-drop ul .links li:hover {
background-color: white;
color: black;
}

#user-drop.open {
display: initial;
}

md-dialog {
position: absolute;
right: 25px;
top: 80px;
}
md-dialog svg {
position: absolute;
left: 16px;
top: 11px;
}

#chat-cntnr {
display: none;
position: fixed;
bottom: 0;
right: 0;
}
#chat-cntnr .chat-box {
height: 150px;
width: 150px;
background-color: blue;
border: 1px solid black;
margin: 0 4px;
}
#chat-cntnr .chat-box:last-child {
margin-right: 0;
}

Answer

I checked out your codepen, and after trying a few things, I noticed the issue is resolved the moment you remove the "scope: $scope" line.
When I looked at the docs for $ngDialog, I found an example that shares the parent scope like you do, but it added an extra option "preserveScope: true". See example from docs below.

// Dialog #3 - Demonstrate use of ControllerAs and passing $scope to dialog
//             Here we used ng-controller="GreetingController as vm" and
//             $scope.vm === <controller instance="">
function showCustomGreeting() {
   $mdDialog.show({
      clickOutsideToClose: true,
      scope: $scope,        // use parent scope in template
      preserveScope: true,  // do not forget this if use parent scope
      // Since GreetingController is instantiated with ControllerAs syntax
      // AND we are passing the parent '$scope' to the dialog, we MUST
      // use 'vm.<xxx>' in the template markup
      template: '<md-dialog>' +
                '  <md-dialog-content>' +
                '     Hi There {{vm.employee}}' +
                '  </md-dialog-content>' +
                '</md-dialog>',
      controller: function DialogController($scope, $mdDialog) {
        $scope.closeDialog = function() {
          $mdDialog.hide();
        }
      }
   });
}

And more details on the scope options from the docs.

scope - {object=}: the scope to link the template / controller to. If none is specified, it will create a new isolate scope. This scope will be destroyed when the dialog is removed unless preserveScope is set to true.

This seems to make your chatDialog too. See updated codepen.


You are using the 'AppCtrl' controller for your dialog. This will re-instantiate the controller inside the dialog. It should look like the following now.

$scope.openChatDialog = function() {
    $mdDialog.show({
      scope: $scope,
      preserveScope: true,
      template: '<md-button ng-click="openChat(\'everybody\')">Everybody</md-button><md-button ng-repeat="user in collaborators" ng-click="openChat(user)"><svg class="status-light" height="17" width="17"><circle cx="8" cy="8" r="8" fill="lightGreen" /></svg>{{user}}</md-button>',
      hasBackdrop: false,
      clickOutsideToClose: true,
      openFrom: '#chat-btn',
      closeTo: '#chat-btn'
    })
  };
Comments