ng-click is not working as it should. I tried looking at documentation and tutorials but couldn't find the reason.
I have a JavaScript variable storing html template. which by using
document.getElementById('someId').innerHTML = emptypage;
where emptypage is a JavaScript variable, is implemented inside a div with id=someId.
My Code:
var emptypage=` <md-toolbar `+ this.createID() +` class="md-accent
soopsObject" ng-app="vdApp">
<span class="example-spacer ng-controller="vdNav">
<md-sidenav class="md-sidenav-left" md-component-id="left" md-
disable-backdrop md-whiteframe="4">
<md-content layout-margin>
<p>
About
</p>
<p>
Contact
</p>
<md-button ng-click="toggleLeft()" class="md-accent">
Close
</md-button>
</md-content>
</md-sidenav>
<div>
<md-button ng-click="toggleLeft()">
<md-icon>menu</md-icon> Menu
</md-button>
</div>
</span>
</md-toolbar>`;
My Controller:
var nav=angular.module("vdApp", []);
nav.controller("vdNav", function($scope, $mdSidenav) {
alert("inside leftToggle");
$scope.toggleLeft = buildToggler('left');
function buildToggler(componentId){
return function(){
$mdSidenav(componentId).toggle();
};
}
});
Even alert isn't working.
What am I doing wrong? Any help or suggestion is appreciated.
Related
Our team is using mdDialog to pull up a modal that allows a user to edit answers to a questionnaire.
$scope.editQuestionFnct = function(val){
$scope.editWidget = {};
//alert(val);
spUtil.get("gateway_questionnaire_widget", {//call new instance of this widget
//sys_id: $scope.params.refID,
task_id: $scope.data.task_id,
quest_id: val,
request: 'edit',
taskTable: $scope.data.task_table,
questionnaire_table: $scope.params.questionnaireTable,
serviceID: $scope.params.serviceID,
refID: $scope.params.refID,
taskCompleted: false,
editRequest: true
}).then(function(response) {
$scope.editWidget = response;//var to hold widget response to display in modal
$scope.showPrerenderedDialog('#editQuestion');
});
}
$scope.showPrerenderedDialog = function(name) {
$mdDialog.show({
templateUrl: name,
parent: angular.element(document.body),
clickOutsideToClose:true
});
};
$scope.closeDialog = function($scope){ //closes angular dialog window
$mdDialog.hide($scope);
}
$scope.closeSummDialog = function($scope){ //closes angular dialog window
$mdDialog.hide($scope);
}
<script type="text/ng-template" id="editQuestion">
<div class="md-dialog-container" >
<md-dialog style="background-color: #ffffff;" aria-label="edit dialog">
<md-toolbar style="background-color: #022C68; width: 100%;">
<h1 class="md-toolbar-tools" style="color: #ffffff;">Edit Response</h1>
</md-toolbar>
<md-dialog-content style="background-color: #ffffff;">
<div id="editQuestDiv" style="min-width: 700px;">
<sp-widget widget="editWidget"></sp-widget>
</div>
</md-dialog-content>
<md-dialog-actions layout="row">
<span flex></span>
<md-button ng-click="closeDialog()" style="background-color: #022C68; color: #ffffff;">
Close
</md-button>
</md-dialog-actions>
</md-dialog>
</div>
</script>
We are experiencing two problems with the above code:
First, instead of using templateUrl, we were using contentElement, which worked. Using contentElement pulled up a modal with the question that required editing. However, when a user clicks out of that first click, and clicks on another question, the same question that appeared in the first click shows up. Every click afterwards will only pull up the question from the first click.
After doing some reading, we decided to try and use templateUrl instead, but using that above opens up a modal with nothing in it:
Can someone explain what we're doing wrong? Are we doing something wrong with contentElement where only the question from the first click persists? If we were to use templateUrl, why isn't our modal showing up?
Thanks!
I have this mark-up html with the #RenderBody():
<div layout="column" class="relative" layout-fill role="main">
<md-toolbar class="md-hue-2">
<div class="md-toolbar-tools">
<md-button class="md-icon-button" aria-label="Settings" ng-disabled="true">
<md-icon md-svg-icon="navigation:menu"></md-icon>
</md-button>
<md-button ui-sref="dashboard">Dashboard</md-button>
<md-button ui-sref="home">Home</md-button>
</div>
</md-toolbar>
<md-content layout-fill md-padding>
<div id="main-content" ui-view="">
#RenderBody()
</div>
</md-content>
</div>
and the js here:
app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/Home/Index');
$stateProvider
.state('home', {
url: '/Home/Index',
templateUrl: '/Home/Index' // corresponds to an MVC partial route
})
.state('dashboard', {
url: 'Home/Dashboard',
templateUrl: '/Home/Dashboard' // corresponds to an MVC partial route
})
});
The result is its own view inside a view. I cant figure it out.
Here is the output:
I see this problem in few of my apps.
Your layout is loading twice.
All you need to do is "make your layout null" while rendering from uiroute as below.
Add this on top of your Index.cshtml page
#{
Layout = null;
}
Or load ui-view out side the content div
<md-content layout-fill md-padding>
<div id="main-content">
#RenderBody()
</div>
</md-content>
<ui-view></ui-view>
Or you could use viewContentLoaded that is triggered after DOM is loaded when using uirouter in angular as below:
//trigger events after DOM content load
$scope.$watch("$viewContentLoaded",
function() {
if (document.getElementsByTagName("header").length === 2) {
document.getElementsByTagName("header")[1].remove();
}
if (document.getElementsByTagName("footer").length === 2) {
document.getElementsByTagName("footer")[1].remove();
}
});
I want to have a sidenav with angular material which has 2 states: collapsed (only icons of the items are shown) and expanded (labes + icons shown). The example behaviour is shown at the RDash Dashboard, which is unfortunetally done with bootstrap.
Since the default sidenav of angular material does not provide that feature, I wanted to do it myself.
I have 2 ideas on how to do it:
1) using 2 different side-navs: one for collapsed, one for expanded. Then switching open-locked between them or just hiding/showing always one at a time.
2) using only 1 sidenav. somehow programmatically change the width, and the items of the sidenav and keeping it open-locked.
My favourite approach would be 2, but I want to know if there are any better ways to achieve that kind of sidenav with angular material?
I think approach 2 is the best - CodePen
Markup
<div ng-controller="AppCtrl" layout="column" style="height:500px;" ng-cloak="" class="sidenavdemoBasicUsage" ng-app="MyApp">
<section layout="row" flex="">
<md-sidenav class="md-sidenav-left" md-component-id="left" md-whiteframe="4" id="leftSideNav">
<md-toolbar class="md-theme-indigo" layout="row">
<h1 class="md-toolbar-tools">Sidenav Left</h1>
<span flex></span>
<md-button ng-click="toggleExpand()">{{toggleExpandButtonLabel}}</md-button>
</md-toolbar>
<md-content layout-padding="">
<md-button ng-click="close()" class="md-primary">
Close Sidenav Left
</md-button>
</md-content>
</md-sidenav>
<md-content flex="" layout-padding="">
<div layout="column" layout-align="top center">
<div>
<md-button ng-click="toggleLeft()" class="md-primary">
Toggle left
</md-button>
</div>
</div>
</md-content>
</section>
</div>
JS
angular
.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('AppCtrl', function ($scope, $timeout, $mdSidenav, $log, $element) {
$scope.toggleLeft = buildToggler('left');
$scope.toggleExpandButtonLabel = "Expand";
var sideNav = angular.element($element[0].querySelector('#leftSideNav'));
$scope.toggleExpand = function () {
if ($scope.toggleExpandButtonLabel == "Expand") {
sideNav.css("width", "500px")
}
else {
sideNav.css("width", "320px")
}
$scope.toggleExpandButtonLabel = ($scope.toggleExpandButtonLabel == "Expand") ? "Collapse" : "Expand";
}
$scope.close = function () {
$mdSidenav('left').close();
$scope.toggleExpandButtonLabel = "Expand";
sideNav.css("width", "320px")
};
function buildToggler(navID) {
return function() {
$mdSidenav(navID)
.toggle()
.then(function () {
$log.debug("toggle " + navID + " is done");
});
}
}
});
Using angular & material, I have a sidenav on the left used to provide user's function (login, signup...).
Working fine, but I want the bar to be closed automatically once the user clicks on a menu. Currently, the bar stays open.
The sidebar code:
<md-sidenav md-component-id="user_sidenav" class="md-sidenav-left" flex>
<md-menu-content flex>
<md-menu-item>
<md-button ui-sref="app.user-state()">
<span>
User
</span>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ui-sref="vlg.user-other-state()">
<span>
Other
</span>
</md-button>
</md-menu-item>
...
Any idea?
What I have done is create a function in the controller for closing the sidenav and then on clicking of an element calling the function.
app.controller('AppController', ['$scope', '$mdSidenav',
function ($scope, $mdSidenav) {
$scope.close = function () {
$mdSidenav('left').close();
};
}]);
and then in html
<div ng-controller="AppController">
<!-- Add in code for sidenav-->
<md-button ng-href="#/path" ng-click="close()"></md-button>
</div>
You could also just add the below code to a function if your elements already have a ng-click attached.
.then(function () {
$mdSidenav('left').close();
});
I tried to add ng-click on a button generated before (dynamic), but didn't work well. Also I tried already all solutions found on this forum and no one work well.
My html code:
<body class="max_height" ng-app="myApp">
<div class="container max_height" ng-controller="myCtrl">
<div id="play" tabindex="0" ng-init="init()" ng-keydown="keyDown($event)">
{{ content }}
</div>
</div>
<script src="js/angular.min.js"></script>
<script src="js/script.js"></script>
</body>
My AngularJS code:
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope, $compile) {
$scope.init = function() {
var el = '<button class="btn" id="start" data-ng-click="startAnimation()">Start</buttom>';
var element = angular.element(document.querySelector('#play'));
var generated = element.html(el);
$compile(generated)($scope);
}
$scope.startAnimation = function(){
console.log("click");
}
});
My error is "RangeError: Maximum call stack size exceeded" and this is generated by $compile(generated)($scope); . Another problem, derived from the first, is that if I make one click on button then the function startAnimation will me executed hundreds of times.
Please give me a solution. Where is the mistake.
Issue is with this line of code:
$compile(generated)($scope);
Instead it should be:
$compile(generated.contents())($scope);
You can assign the function to a scope variable and depending on your business logic assign appropriate functions to your ng-click. In the below example $scope.addGeoFence() is added to the ng-click of "Add GeoFence" list-item
$scope.layout = [
{name: 'Home', icon: 'home'},
{name: 'Add Geofence',
icon: 'add_location',
click: $scope.addGeoFence}
];
$scope.addGeoFence = function() {
console.log("calling addGeoFence()");
}
<md-list>
<md-list-item ng-repeat="snav in layout">
<md-button class="md-raised" ng-click="(snav.click)()" flex>
<md-icon md-font-library="material-icons">{{snav.icon}}
</md-icon>
<span>{{snav.name}}</span>
</md-button>
</md-list-item>
</md-list>