How to check conditions in angularjs - angularjs

I am trying to open up a modal in my application, based on particular click it should open that respective modal.I tried ng-if and ng-switch concept but it didn't worked. So please help me..,
Thanks!
Here is my code..,
<div ng-controller="projectsController">
<ul>
<li>Bangalore</li>
<li>Mangalore</li>
<li>Mysore</li>
</ul>
<div ng-switch on="id">
<div ng-switch-when="A">
<modal-dialog show='modalShown' width='800px' height='50%'>
<p>Modal Content Goes here</p>
</modal-dialog>
</div>
<div ng-switch-when="B">
<modal-dialog show='modalShown' width='800px' height='50%'>
<p>Second Modal Content Goes here</p>
</modal-dialog>
</div>
</div>
</div>
/*app.js file*/
myApp.controller('projectsController', ['$scope', function($scope) {
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
}]);
//This is my directive in app.js i.e.,both controller and directive are in
app.js file
myApp.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '='
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
scope.hideModal = function() {
scope.show = false;
};
},
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay' ng-click='hideModal()'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'>X</div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
};
});

I'm not sure where the modal-dialog directive is coming from but it's possible the show attribute in it expects an expression. You might want to change it to:
<modal-dialog show="modalShown === true" width="800px" height="50%">

Related

Variable value not passing in a controller using directive with ng-class

I am referencing the value of the variable in a controller in an ng-class template but its not working.
here is the html directive template URl :
<div class="tooltip-anchor">
<div class=" tooltip-content ehub-body" ng-class="{ 'tooltip__content--disabled': tooltipContentValue}" ng-transclude>Tooltip content</div>
</div>
Here is where i am using the directive in the index page
<div style="text-align:center;">
<ehub-tooltip>Hello i am here, and i am her to stay</ehub-tooltip>over here
<ehub-tooltip>Be nice to people on your way up and they will be nice to you on your way down</ehub-tooltip>click me
</div>
And here is the directive:
in this directive i am creating a variable and setting it to false and also trying to use it in an ng-class attribute
(function (window) {
'use strict';
angular
.module('ehub.component.tooltip', [])
.controller('ehubTooltipCtrl', ['$scope', function ($scope) {
$scope.tooltipContentValue = false;
}])
.directive('ehubTooltip', ehubTooltip);
function ehubTooltip() {
var directive = {
controller: "ehubTooltipCtrl",
link: link,
transclude: true,
templateUrl: 'ehub-tooltip.html',
restrict: 'E'
};
return directive;
function link(scope, element, attrs) {
scope.keyupevt = function () {
if (event.keyCode === 27) {
$scope.tooltipContentValue = true;
}
}
}
}
})();
Try this working jsfiddle.
angular.module('ExampleApp', ['ngMessages'])
.controller('ExampleController', function($scope) {
})
.directive('ehubTooltip', function() {
var directive = {
link: link,
transclude: true,
template: '<div class="tooltip-anchor"><div class=" tooltip-content ehub-body" ng-class="{ \'tooltip__content--disabled\': tooltipContentValue}" ng-transclude>Tooltip content</div></div>',
restrict: 'E'
};
function link(scope, element, attrs) {
scope.tooltipContentValue = false;
scope.keyupevt = function() {
if (event.keyCode === 27) {
scope.tooltipContentValue = true;
}
}
}
return directive;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleController">
<div style="text-align:center;">
<a href="" ng-keyup="keyupevt()">
<ehub-tooltip>Hello i am here, and i am her to stay</ehub-tooltip>over here</a>
<a href="" ng-keyup="keyupevt()">
<ehub-tooltip>Be nice to people on your way up and they will be nice to you on your way down</ehub-tooltip>click me</a>
</div>
</div>
</div>

Angular JS change property of controller for directive

I am trying to change boolean property of my controller from directive. It is set to true, but when i set it to false it should display other html template. Her is my code:
Directive code:
app.directive('entityTaskList', function(){
return {
restrict: 'E',
templateUrl: 'views/task/taskList.html',
scope: {
taskItems: '='
},
bindToController: true,
controller: 'TasksCtrl as taskCtrl',
link: function(scope, element, attrs){
scope.openItem = function(){
console.log("Open Items");
var ctrl = scope.taskCtrl;
ctrl.newTask = false;
};
}
};
});
TaskCtrl code:
app.controller('TasksCtrl', ['$scope', 'TaskService', function ($scope, TaskService) {
// initialize function
this.newTask = true;
this.name = "Nedim";
this.templates = {
new: "views/task/addTask.html",
view: "views/task/viewTask.html"
};
// load all available tasks
TaskService.loadAllTasks().then(function (data) {
$scope.items = data.tasks;
});
$scope.$on('newTaskAdded', function(event, data){
$scope.items.concat(data.data);
});
return $scope.TasksCtrl = this;
}]);
taskList.html
<ul class="list-group">
<li ng-repeat="item in taskCtrl.taskItems" class="list-group-item">
<a ng-click="openItem()">
<span class="glyphicon glyphicon-list-alt" aria-hidden="true"> </span>
<span>{{item.name}}</span>
<span class="task-description">{{item.description}}</span>
</a>
</li>
</ul>
and task.html
<!-- Directive showing list of available tasks -->
<div class="container-fluid">
<div class="row">
<div class="col-sm-6">
<entity-task-list task-items="items"></entity-task-list>
</div>
<div class="col-sm-6" ng-controller="TaskDetailCtrl as taskDetailCtrl">
<!-- form for adding new task -->
<div ng-show="taskCtrl.newTask" ng-include="taskCtrl.templates.new"></div>
<!-- container for displaying existing tasks -->
<div ng-show="!taskCtrl.newTask" ng-include="taskCtrl.templates.view"></div>
</div>
</div>
</div>
If you change this:
// load all available tasks
TaskService.loadAllTasks().then(function (data) {
$scope.items = data.tasks;
});
To this(literally):
// load all available tasks
TaskService.loadAllTasks().then(function (data) {
this.items = data.tasks;
});
your code will work, this is due to you using the controllerAs syntax for TaskCtrl but not assigning it to this instead to the $scope

Toggling a Twitter Bootstrap (3.x) Modal using AngularJS

I've been trying to get a Bootstrap Model to be hidden on load, and then show it after clicking a button, but have been unsuccessful so far. I am pretty new to AngularJS so bear with me if I'm not doing this correctly. Here's what I've got so far:
Modal Angular Directive (modal.js):
angular.module('my.modal', ['modal.html'])
.directive('myModal', function () {
return {
restrict: 'E',
transclude: true,
replace: false,
templateUrl: 'modal.html',
link: function(scope, element, attrs) {
element.modal('hide')
scope.toggleModal = function() {
if (attrs.showModal === true) {
element.modal('hide')
attrs.showModal = false
} else {
element.modal('show')
attrs.showModal = true
}
}
}
};
});
Modal Template (modal.html):
<div id="{{id}}" showModal="false" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<div class="content" ng-transclude></div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="showModal = false">Cancel</button>
</div>
</div>
</div>
</div>
And finally, the button to toggle the modal (index.html):
...
<my-modal>
<p>Some content</p>
</my-modal>
<button class="btn btn-default" type="button" ng-click="toggleModal()">Toggle me!</button>
...
All this does is show the modal on page load (between my header and all the other content, so it's not floating above anything) and the toggle button does not work.
I've managed to get it working by using the Bootstrap 3 Modal properties and dynamically changing styling and classes of the modal directive based on it's show or hide state, though there are no animations:
Modal Angular Directive (modal.js):
angular.module('my.modal', ['modal.html'])
.directive('myModal', [function () {
return {
restrict: 'E',
transclude: true,
replace: false,
templateUrl: 'modal.html',
controller: 'ModalCtrl',
link: function(scope, element, attrs) {
if (attrs.title === undefined) {
scope.title = 'Modal Title Placeholder';
} else {
scope.title = attrs.title;
}
scope.$watch('showModal', function (value) {
if (value) {
scope.displayStyle = 'block';
scope.modalFadeIn = 'in';
} else {
scope.displayStyle = 'none';
scope.modalFadeIn = '';
}
});
}
};
}).controller('ModalCtrl', ['$scope', function ($scope) {
$scope.toggleModal = function() {
$scope.showModal = !$scope.showModal;
};
$scope.$open = function() {
$scope.showModal = true;
};
$scope.$close = function() {
$scope.showModal = false;
};
});
Modal Template (modal.html):
<div role="dialog" tabindex="-1" class="modal fade" ng-init="showModal = false" ng-show="showModal" ng-style="{display: displayStyle}" ng-class="modalFadeIn">
<div class="modal-backdrop fade in" style="height: 100%"> </div>
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">{{title}}</h3>
</div>
<div class="modal-body">
<div class="content" ng-transclude></div>
</div>
</div>
</div>
</div>
The call to open the modal can be done using the open or toggleModal function. A custom button needs to be placed in the modal to close the modal.

AngularJS reusable modal bootstrap directive

I'm new with AngularJS. I'm trying to implement a reusable modal Bootstrap.
This is the index.html:
<div ng-controller="mymodalcontroller">
<modal lolo="modal1" modal-body='body' modal-footer='footer' modal-header='header' data-ng-click="myRightButton()"></modal>
Launch Demo Modal
</div>
This is the module, controller and directive:
var myModal = angular.module('myModal', []);
myModal.controller('mymodalcontroller', function ($scope) {
$scope.header = 'Put here your header';
$scope.body = 'Put here your body';
$scope.footer = 'Put here your footer';
$scope.myRightButton = function (bool) {
alert('!!! first function call!');
};
});
myModal.directive('modal', function () {
return {
restrict: 'EA',
scope: {
title: '=modalTitle',
header: '=modalHeader',
body: '=modalBody',
footer: '=modalFooter',
callbackbuttonleft: '&ngClickLeftButton',
callbackbuttonright: '&ngClick',
handler: '=lolo'
},
templateUrl: 'partialmodal.html',
transclude: true,
controller: function ($scope) {
$scope.handler = 'pop';
},
};
});
And this is the html template:
<div id="{{handler}}" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">{{header}}</h4>
</div>
<div class="modal-body">
<p class="text-warning">{{body}}</p>
</div>
<div class="modal-footer">
<p class="text-left">{{footer}}</p>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-ng-click="callbackbuttonright(), $event.stopPropagation()">Save changes</button>
</div>
</div>
</div>
</div>
I want the 'Launch Alert' button (in the modal) executes the alert and it does it well. The problem is that it is launched when clicking the 'Cancel' button in the Modal and when the window closes. Any ideas?
Here is the working code:CodeThank you.
I would suggest you not bind to ng-click. It does some other magic stuff that can screw with things. There is also a syntax error in your partial.
I've fixed those issues in my fork here:
http://plnkr.co/edit/2jK2GFcKSiKgMQMynD1R?p=preview
To summarize:
script.js:
Change your callbackbuttonright binding from ngClick to ngClickRightButton
myModal.directive('modal', function () {
return {
restrict: 'EA',
scope: {
title: '=modalTitle',
header: '=modalHeader',
body: '=modalBody',
footer: '=modalFooter',
callbackbuttonleft: '&ngClickLeftButton',
callbackbuttonright: '&ngClickRightButton',
handler: '=lolo'
},
templateUrl: 'partialmodal.html',
transclude: true,
controller: function ($scope) {
$scope.handler = 'pop';
},
};
});
index.html:
Change data-ng-click to data-ng-click-right-button
<modal lolo="modal1" modal-body="body" modal-footer="footer" modal-header="header" data-ng-click-right-button="myRightButton()"></modal>
Another minor issue:
partialmodal.html:
Change , to ;
<button type="button" class="btn btn-primary" data-ng-click="callbackbuttonright(); $event.stopPropagation()">Launch Alert</button>
If anyone is still interested, here is a example I recently worked on with bootstrap modal and angularjs directive.
HTML:
<modal visible="showModal1" on-sown="modalOneShown()" on-hide="modalOneHide()">
<modal-header title="Modal Titel 1"></modal-header>
<modal-body>
<h3>This is modal body</h3>
</modal-body>
<modal-footer>
<button class="btn btn-primary" ng-click="hide(1)">Save</button>
</modal-footer>
</modal>
JavaScript:
var myModalApp = angular.module('myModalApp',[]);
myModalApp.directive('modal', function(){
return {
template: '<div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true"><div class="modal-dialog modal-sm"><div class="modal-content" ng-transclude><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button><h4 class="modal-title" id="myModalLabel">Modal title</h4></div></div></div></div>',
restrict: 'E',
transclude: true,
replace:true,
scope:{visible:'=', onSown:'&', onHide:'&'},
link:function postLink(scope, element, attrs){
$(element).modal({
show: false,
keyboard: attrs.keyboard,
backdrop: attrs.backdrop
});
scope.$watch(function(){return scope.visible;}, function(value){
if(value == true){
$(element).modal('show');
}else{
$(element).modal('hide');
}
});
$(element).on('shown.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = true;
});
});
$(element).on('shown.bs.modal', function(){
scope.$apply(function(){
scope.onSown({});
});
});
$(element).on('hidden.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = false;
});
});
$(element).on('hidden.bs.modal', function(){
scope.$apply(function(){
scope.onHide({});
});
});
}
};
}
);
myModalApp.directive('modalHeader', function(){
return {
template:'<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button><h4 class="modal-title">{{title}}</h4></div>',
replace:true,
restrict: 'E',
scope: {title:'#'}
};
});
myModalApp.directive('modalBody', function(){
return {
template:'<div class="modal-body" ng-transclude></div>',
replace:true,
restrict: 'E',
transclude: true
};
});
myModalApp.directive('modalFooter', function(){
return {
template:'<div class="modal-footer" ng-transclude></div>',
replace:true,
restrict: 'E',
transclude: true
};
});
function ModalController($scope){
$scope.title = "Angularjs Bootstrap Modal Directive Example";
$scope.showModal1 = false;
$scope.showModal2 = false;
$scope.hide = function(m){
if(m === 1){
$scope.showModal1 = false;
}else{
$scope.showModal2 = false;
}
}
$scope.modalOneShown = function(){
console.log('model one shown');
}
$scope.modalOneHide = function(){
console.log('model one hidden');
}
}
Compared to other options, below given the minimalist approach using Angular Bootstrap and an angular factory. See a sample snippet below.
Reusable modal view - ConfirmationBox.html
<div class="modal-header">
<h3 class="modal-title">{{title}}</h3>
</div>
<div class="modal-body">
{{message}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary btn-warn" data-ng-click="ok(); $event.stopPropagation()">OK</button>
<button type="button" class="btn btn-default" data-ng-click="cancel(); $event.stopPropagation()">Cancel</button>
</div>
Reusable module and shared factory, for handling the reusable modal dialog
angular.module('sharedmodule',['ui.bootstrap', 'ui.bootstrap.tpls'])
.factory("sharedService",["$q", "$modal", function ($q, $modal)
{
var _showConfirmDialog = function (title, message)
{
var defer = $q.defer();
var modalInstance = $modal.open({
animation: true,
size: "sm",
templateUrl: 'ConfirmationBox.html',
controller: function ($scope, $modalInstance)
{
$scope.title = title;
$scope.message = message;
$scope.ok = function ()
{
modalInstance.close();
defer.resolve();
};
$scope.cancel = function ()
{
$modalInstance.dismiss();
defer.reject();
};
}
});
return defer.promise;
}
return {
showConfirmDialog: _showConfirmDialog
};
}]);
Portion of your View, using the shared modal dialog
<a data-ng-click="showConfirm()">Go Back to previous page</a>
Controller of your view, opening your shared reusable modal dialog and handling notifications (Ok and Cancel)
var myModule = angular.module("mymodule", ['sharedmodule', 'ui.bootstrap', 'ui.bootstrap.tpls']);
myModule.controller('myController', ["$scope", "sharedService", "$window",
function ($scope, sharedService, $window)
{
$scope.showConfirm = function ()
{
sharedService.showConfirmDialog(
'Confirm!',
'Any unsaved edit will be discarded. Are you sure to navigate back?')
.then(function ()
{
$window.location = '#/';
},
function ()
{
});
};
}]);

Angular.js directive dynamic templateURL

I have a custom tag in a routeProvider template that that calls for a directive template. The version attribute will be populated by the scope which then calls for the right template.
<hymn ver="before-{{ week }}-{{ day }}"></hymn>
There are multiple versions of the hymn based on what week and day it is. I was anticipating to use the directive to populate the correct .html portion. The variable is not being read by the templateUrl.
emanuel.directive('hymn', function() {
var contentUrl;
return {
restrict: 'E',
link: function(scope, element, attrs) {
// concatenating the directory to the ver attr to select the correct excerpt for the day
contentUrl = 'content/excerpts/hymn-' + attrs.ver + '.html';
},
// passing in contentUrl variable
templateUrl: contentUrl
}
});
There are multiple files in excerpts directory that are labeled before-1-monday.html, before-2-tuesday.html, …
emanuel.directive('hymn', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
// some ode
},
templateUrl: function(elem,attrs) {
return attrs.templateUrl || 'some/path/default.html'
}
}
});
So you can provide templateUrl via markup
<hymn template-url="contentUrl"><hymn>
Now you just take a care that property contentUrl populates with dynamically generated path.
You can use ng-include directive.
Try something like this:
emanuel.directive('hymn', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
scope.getContentUrl = function() {
return 'content/excerpts/hymn-' + attrs.ver + '.html';
}
},
template: '<div ng-include="getContentUrl()"></div>'
}
});
UPD. for watching ver attribute
emanuel.directive('hymn', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
scope.contentUrl = 'content/excerpts/hymn-' + attrs.ver + '.html';
attrs.$observe("ver",function(v){
scope.contentUrl = 'content/excerpts/hymn-' + v + '.html';
});
},
template: '<div ng-include="contentUrl"></div>'
}
});
Thanks to #pgregory, I could resolve my problem using this directive for inline editing
.directive("superEdit", function($compile){
return{
link: function(scope, element, attrs){
var colName = attrs["superEdit"];
alert(colName);
scope.getContentUrl = function() {
if (colName == 'Something') {
return 'app/correction/templates/lov-edit.html';
}else {
return 'app/correction/templates/simple-edit.html';
}
}
var template = '<div ng-include="getContentUrl()"></div>';
var linkFn = $compile(template);
var content = linkFn(scope);
element.append(content);
}
}
})
You don't need custom directive here. Just use ng-include src attribute. It's compiled so you can put code inside. See plunker with solution for your issue.
<div ng-repeat="week in [1,2]">
<div ng-repeat="day in ['monday', 'tuesday']">
<ng-include src="'content/before-'+ week + '-' + day + '.html'"></ng-include>
</div>
</div>
I had the same problem and I solved in a slightly different way from the others.
I am using angular 1.4.4.
In my case, I have a shell template that creates a CSS Bootstrap panel:
<div class="class-container panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">{{title}} </h3>
</div>
<div class="panel-body">
<sp-panel-body panelbodytpl="{{panelbodytpl}}"></sp-panel-body>
</div>
</div>
I want to include panel body templates depending on the route.
angular.module('MyApp')
.directive('spPanelBody', ['$compile', function($compile){
return {
restrict : 'E',
scope : true,
link: function (scope, element, attrs) {
scope.data = angular.fromJson(scope.data);
element.append($compile('<ng-include src="\'' + scope.panelbodytpl + '\'"></ng-include>')(scope));
}
}
}]);
I then have the following template included when the route is #/students:
<div class="students-wrapper">
<div ng-controller="StudentsIndexController as studentCtrl" class="row">
<div ng-repeat="student in studentCtrl.students" class="col-sm-6 col-md-4 col-lg-3">
<sp-panel
title="{{student.firstName}} {{student.middleName}} {{student.lastName}}"
panelbodytpl="{{'/student/panel-body.html'}}"
data="{{student}}"
></sp-panel>
</div>
</div>
</div>
The panel-body.html template as follows:
Date of Birth: {{data.dob * 1000 | date : 'dd MMM yyyy'}}
Sample data in the case someone wants to have a go:
var student = {
'id' : 1,
'firstName' : 'John',
'middleName' : '',
'lastName' : 'Smith',
'dob' : 1130799600,
'current-class' : 5
}
I have an example about this.
<!DOCTYPE html>
<html ng-app="app">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container-fluid body-content" ng-controller="formView">
<div class="row">
<div class="col-md-12">
<h4>Register Form</h4>
<form class="form-horizontal" ng-submit="" name="f" novalidate>
<div ng-repeat="item in elements" class="form-group">
<label>{{item.Label}}</label>
<element type="{{item.Type}}" model="item"></element>
</div>
<input ng-show="f.$valid" type="submit" id="submit" value="Submit" class="" />
</form>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<script src="app.js"></script>
</body>
</html>
angular.module('app', [])
.controller('formView', function ($scope) {
$scope.elements = [{
"Id":1,
"Type":"textbox",
"FormId":24,
"Label":"Name",
"PlaceHolder":"Place Holder Text",
"Max":20,
"Required":false,
"Options":null,
"SelectedOption":null
},
{
"Id":2,
"Type":"textarea",
"FormId":24,
"Label":"AD2",
"PlaceHolder":"Place Holder Text",
"Max":20,
"Required":true,
"Options":null,
"SelectedOption":null
}];
})
.directive('element', function () {
return {
restrict: 'E',
link: function (scope, element, attrs) {
scope.contentUrl = attrs.type + '.html';
attrs.$observe("ver", function (v) {
scope.contentUrl = v + '.html';
});
},
template: '<div ng-include="contentUrl"></div>'
}
})

Resources