AngularJS custom directive initial loading not working - angularjs

You can see the working example here - or should I say, non-working example.
Basically, I'm trying to make a custom directive called yesno-group. It is a shortcut to do this over and over:
<div class="btn-group">
<button type="button" class="btn btn-default" ng-model="checkboxField" btn-radio="true">Yes</button>
<button type="button" class="btn btn-default" ng-model="checkboxField" btn-radio="false">No</button>
</div>
And here is my yesno-group directive:
myApp.directive('yesnoGroup', function () {
return {
restrict: 'A',
scope: {
field: '=',
buttonClass: '#'
},
replace: true,
template: '<div class="btn-group">' +
' <button type="button" class="{{buttonClass}}" ng-model="field" btn-radio="true">Yes</button>' +
' <button type="button" class="{{buttonClass}}" ng-model="field" btn-radio="false">No</button>' +
'</div>'
};
});
The problem is, yesno-group does not show the value on the initial load. But once you start changing the value, it gets synchronized with the ngModel field.
What am I missing?
Also, how can I make the yesno-group to accept ng-model and use it instead of field? I got that from JsFiddle-Examples - currency input, but wish to use ng-model unless it is a big hassle.
Thank you!

You need to use ng-class, not class.
http://jsfiddle.net/KT6Zd/12/
myApp.directive('yesnoGroup', function () {
return {
restrict: 'A',
scope: {
field: '=',
buttonClass: '#'
},
replace: true,
template: '<div class="btn-group">' +
' <button type="button" ng-class="buttonClass" ng-model="field" btn-radio="true">Yes</button>' +
' <button type="button" ng-class="buttonClass" ng-model="field" btn-radio="false">No</button>' +
'</div>'
};
});

Related

disable submit button in directive

I simply want to add the class disable when form.$valid is false. The first submit button (not directive) obiouvsly works, but I don't know how to make visible the form state inside the directive. I cannot hardcode the form name in directive, it should be reusable in several forms..
<form id="tA" name="form" ng-controller="ctrl" ng-submit="form.$valid && save()" novalidate>
<input type="text" class="form-control" placeholder="title" name="name" ng-model="model.name" required ng-required="true">
<button class="btn btn-default" ng-class="{'disabled' : !form.$valid}" class="btn btn-default">Submit</button>
<button-raised disabled="!form.$valid">directive Submit</button-raised>
app.directive('buttonRaised', function() {
return {
restrict: 'E',
template: '<button class="mdl-button" ng-class="ngClass" ng-transclude></button>',
scope: {
ngModel: '='
},
transclude: true,
link: function($scope, el, $attrs,formCtrl) {
console.log(formCtrl)
$scope.ngClass = {
// 'disabled': $scope.$parent.formCtrl.$valid,
};
}
};
});
one way to do this is to pass your boolean as a parameter of your directive :
app.directive('buttonRaised', function() {
return {
restrict: 'E',
template: '<button class="mdl-button" ng-disabled="disabled" ng-class="ngClass" ng-transclude></button>',
scope: {
ngModel: '=',
disabled: '='
},
transclude: true,
link: function($scope, el, $attrs,formCtrl) {
console.log(formCtrl)
$scope.ngClass = {
// 'disabled': $scope.$parent.formCtrl.$valid,
};
}
};
});
You can change the directive and html as per this working this
The directive
app.directive('buttonRaised', function() {
return {
restrict: 'E',
template: '<button class="mdl-button" ng-class="{\'disabled\': disableButton}" ng-transclude></button>',
scope: {
disableButton: '='
},
transclude: true,
link: function($scope, el, $attrs,formCtrl) {
console.log(formCtrl)
}
};
});
The html
<form id="tA" name="form" ng-controller="ctrl" ng-submit="form.$valid && save()" novalidate>
<input type="text" class="form-control" placeholder="title" name="name" ng-model="model.name" required ng-required="true">
<button class="btn btn-default" ng-class="{'disabled' : !form.$valid}" class="btn btn-default">Submit</button>
// directive taking parameter disable-button
<button-raised disable-button="!form.$valid">directive Submit</button-raised>

Input value from a specialized controller isn't being sent back to the main controller

I'm building an application that's making use of Angular UI Bootstrap's datepicker in several spots. I've included some other enhancements to this, such as validation styling, and wanted to propagate it everywhere so I put it in a directive.
app.controller('DateController', function () {
var vm = this;
vm.status = {
opened: false
};
vm.open = open;
function open($event) {
vm.status.opened = true;
}
});
app.directive('customDatePicker', function () {
return {
restrict: 'E',
scope: {
name: '=',
bindingProperty: '=',
minDate: '=',
maxDate: '=',
maxMode: '=',
format: '=',
isRequired: '=',
form: '='
},
templateUrl: "/Scripts/SharedAngular/Templates/datePicker.html"
};
});
With the template URL code looking like:
<div ng-controller="DateController as datePicker">
<p class="input-group">
<input type="text" id="{{ name }}_datePicker" name="{{ name }}_datePicker" class="form-control" max-mode="maxMode" datepicker-popup="{{format}}" ng-model="bindingProperty" min-date="minDate" max-date="maxDate" ng-required="isRequired" close-text="Close" is-open="datePicker.status.opened" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="datePicker.open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
<span ng-show="form.{{ name }}_datePicker.$invalid && form.{{ name }}_datePicker.$dirty" class="glyphicon glyphicon-exclamation-sign form-control-feedback datepicker-error-icon"></span>
</p>
</div>
I'm including this directive in a couple places. It is placed on a page within the scope of a different controller like this:
<div ng-controller="myController as ctrl">
<custom-date-picker name="'somePrefix'" form="myForm" binding-property="ctrl.date" max-mode="'month'" max-date="ctrl.currentDate" format="'yyyy/MM/dd'" is-required="true"></custom-date-picker>
</div>
So, I want to take a property from myController and two-way bind it to the directive's date picker. However, what ends up actually happening is that the current value for ctrl.date property is passed to the datepicker, but any changes to that value that happen in the directive are not sent back. So, it seems that myController and DateController only pass the value one-way, and only when the directive is loaded onto the page. To be clear, the directive doesn't seem to be the source of my issue, since putting the HTML code from the template directly onto my page results in the same behavior. So, it appears that the issue is specifically due to the use of two different controllers.
Previously, I was using ng-model both in the template code and the directive on my primary page. Neither option seems to work. I'm open to any ideas on how to get the input from my directive to be sent back to the myController.
I figured out how to ditch the DateController entirely. I put my expressions directly into the template elements via ng-click and ng-init. The input creates a property called opened and uses ng-init initializes it to false. It then uses that property for the is-open attribute of the datepicker. Then the button just uses ng-click="opened=true". Definitely simplifies things and removes the nesting of controllers.
Directive:
app.directive('customDatePicker', function () {
return {
restrict: 'E',
scope: {
name: '=',
bindingProperty: '=ngModel',
minDate: '=',
maxDate: '=',
maxMode: '=',
format: '=',
isRequired: '=',
form: '='
},
require: 'ngModel',
templateUrl: "/Scripts/SharedAngular/Templates/datePicker.html"
};
});
Template:
<p class="input-group">
<input type="text" id="{{ name }}_datePicker" name="{{ name }}_datePicker" class="form-control" max-mode="maxMode" datepicker-popup="{{format}}" ng-model="bindingProperty" min-date="minDate" max-date="maxDate" ng-required="isRequired" close-text="Close" is-open="opened" ng-init="opened=false" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="opened=true"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
<span ng-show="form.{{ name }}_datePicker.$invalid && form.{{ name }}_datePicker.$dirty" class="glyphicon glyphicon-exclamation-sign form-control-feedback datepicker-error-icon"></span>
</p>
Using the directive:
<div ng-controller="MyController as ctrl">
<custom-date-picker name="'somePrefix'" form="myForm" ng-model="ctrl.Date" max-mode="'month'" max-date="ctrl.currentDate" format="'yyyy/MM/dd'" is-required="true"></custom-date-picker>
</div>

Not able to close modal window by function

I am using modal like
<modal title="Success" id='successmessage' visible="successmessage">
<form role="form">
Success ful result.
<button type="submit" class="btn btn-primary" ng-click="closesuccessmessage()" >Ok</button>
</form>
</modal>
I have a directive on modal..
'use strict';
angular.module('abc.directives', [])
.directive('modal', function () {
return {
template: '<div 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">{{ modalTitle }}</h4>' +
'</div>' +
'<div class="modal-body" ng-transclude></div>' +
'</div>' +
'</div>' +
'</div>',
restrict: 'E',
transclude: true,
replace:true,
scope:true,
link: function postLink(scope, element, attrs) {
scope.modalTitle = attrs.title;
scope.$watch(attrs.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('hidden.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = false;
});
});
}
};
});
in my angular controller i have created function like below
$scope.closesuccessmessage = function()
{
$scope.successmessage = false;
}
But it does not have any effect. How can i make it work. As it is very important for me to control this from a function. Modal opens up on true value, but does not close on false value.
In order for angularjs to bind variable to view outside of properties expecting expressions you must use brackets.
<modal title="Success" id='successmessage' visible="{{successmessage}}">
<form role="form">
Success ful result.
<button type="submit" class="btn btn-primary" ng-click="closesuccessmessage()" >Ok</button>
</form>
</modal>
However I'm not sure visible is a valid property in HTML. If you want to hide modal using variable you could use ng-show and set success message variable in controller
<modal title="Success" id='successmessage' ng-show="successmessage">
<form role="form">
Success ful result.
<button type="submit" class="btn btn-primary" ng-click="closesuccessmessage()" >Ok</button>
</form>
</modal>
You can't use like above you're doing. You should call modal hide function to hide a modal. Try below snippet
$scope.closesuccessmessage = function()
{
$("#successmessage").modal('hide');
}
EDIT
It's not like that you can't use scope values in your HTML. If your controller is same, you can access it easily. I changed your HTML. Please try below one
<modal title="Success" id='successmessage' data-ng-show="successmessage">
instead
<modal title="Success" id='successmessage' visible="successmessage">

Conditional logic in ng-class in directives template

I'm using AngularJS and i'm writing my own directive. I want to use conditional logic in my custom directive. The problem is caused in the template part. Here's a piece of my code:
angular.module('myDirectives').directive('widget', function() {
return {
replace: true,
restrict: 'E',
template:
'<div class="widget">' +
'<div class="panel panel-default">' +
'<div class="panel-heading">' +
'<a href="" class="btn btn-default" ng-click="isCollapsed = !isCollapsed">' +
'<i class="fa" ng-class=" { 'fa-angle-up': !isCollapsed, 'fa-angle-down': isCollapsed } "></i>' +
'</a>' +
'</div>' +
'<div class="panel-body" collapse="isCollapsed">' +
'<p>Panel Content</p>' +
'</div>' +
'</div>' +
'</div>',
transclude: true
}
});
This line throws an error.
'<i class="fa" ng-class=" { 'fa-angle-up': !isCollapsed, 'fa-angle-down': isCollapsed } "></i>'
The '' around fa-angle-up and fa-angle-down are causing this.
There's probably a very simple workaround, but I haven't figured it out yet. So my question for you guys; Is there any other way to write this line?
You have to escape the apostrophes
'<i class="fa" ng-class=" { \'fa-angle-up\': !isCollapsed, \'fa-angle-down\': isCollapsed } "></i>'

Angular Bootstrap Datepicker directive to minimize html elements

We are using Angular UI bootstrap implementation for date picker in our project. I need to write many HTML element for date picker, would it be a good idea to write a directive for such tasks? If yes please help me to provide sample code for any such directive.
<p class="input-group">
<input type="text" class="form-control" datepicker-popup ng-model="leaveSearch.td" is-open="$parent.dtLeaveToOpen" ng-required="true" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="datePickerOpen($event,'dtLeaveTo','dtLeaveToOpen')"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
How can wrap all this into single html element, I think using Angular directive we can achieve this. I am looking for similar idea.
Finally I wrote below directive which worked for me:
angularStartDirectives.directive('espireDate', function () {
return {
restrict: 'E',
scope: {
show: '=',
ngModel: '=',
ngClass: '=',
ngRequired:'='
},
replace: true, // Replace with the template below
transclude: true, // we want to insert custom content inside the directive
require: 'ngModel',
link: function (scope, element, attrs) {
scope.open = false;
scope.dpOpen = function () {
scope.open = true;
};
},
template: '<div><div class="input-group input-group-lg" ng-click="dpOpen()" >'
+ ' <input id="attrs.id" readonly="true" type="text" class="form-control" data-is-open="open" datepicker-popup data-ng-model="ngModel" ng-class="ngClass" ng-required="ngRequired" />'
+ ' <span class="input-group-addon">'
+ '<span class="glyphicon glyphicon-calendar"></span>'
+ '</span></div></div>'
};
});

Resources