I've created a directive that show a calender like this :
app.directive('noeDatepicker', ['$parse', 'datetimeService', function ($parse, datetimeService) {
return {
restrict: 'E',
templateUrl: '/app/directives/templates/datepicker.html',
scope: {
model: '=',
withisrequired: '#'
},
require: '^form',
replace: true,
link: function (scope, element, attrs, ctrl) {
scope.buttonId = 'date_icon_' + attrs.id;
scope.inputId = 'date_input_' + attrs.id;
scope.cancelId = 'date_cancel_' + attrs.id;
setTimeout(function () {
Calendar.setup({...});
}
};
}
});
and my template is this :
<div ng-model="model" class="form-inline">
<input id="{{inputId}}" class="form-control" type="text" isrequired="{{withisrequired}}" ng-model="model" placeholder="1111/01/01" />
<img id="{{cancelId}}" src="/Content/noe/assets/image/icon/Cancle.svg" width="22" height="22" />
<img id="{{buttonId}}" src="/Scripts/jalalijscalendar/cal.png" />
</div>
but my problem is that when I wanna add for example ng-readonly to this directive, it just add readonly property to div element and input element is not readonly and it accept input from user (see code bellow) :
<noe:datepicker model="viewModel.date" id="date1" name="date1" ng-readonly="true" />
I want this ng-readonly function also make all child element in div tag readonly and not just add readonly proptety to div element!
How can i Do that ?
Update noeDatepicker with
scope:{
readonly:'=ngReadonly',
...
},
template: <div> <input ng-readonly="readonly"/> </div> ...
basically, you need to add ng-readonly for children elements you want to set.
Related
Okay, so here's my custom directive:
angular.module('bulwarkWebControls', [])
.directive('dropdownList', [
function() {
return {
scope: {
label: '#', // optional
changeCallback: '&',
options: '=',
required: "=",
disabled: "=",
id: "=",
name: "=",
model: "=",
value: "=",
display: "="
},
restrict: 'E',
replace: true, // optional
templateUrl: 'app/templates/dropDownList.html',
link: {
pre: function (scope, element, attr) {
scope.expression = "o."+value +" as o."+display+" for o in options";
}
}
};
}
]);
Template:
<div class="row form-group form-horizontal">
<label data-for="id" class="control-label col-md-3">{{label}}</label>
<div class="col-md-9">
<select data-id="id" data-name="name" data-ng-disabled="disabled" class="form-control"
data-ng-model="model"
data-ng-options="{{expression}}" data-ng-required="required">
<option></option>
</select>
</div>
Html code that utilizes the directive:
<div>
<dropdown-list data-label="Phone(s)" data-id="phoneList" data-name="phoneList"
data-disabled="vm.workOrder.Contacted"
data-model="vm.workOrder.PhoneNumber_Id" data-value="Id" data-display="Number"
data-options="vm.workOrder.CustomerPhoneNumbers" data-required="vm.workOrder.SpokeTo_Id!=5" />
</div>
What I am trying to do is basically create the expression for the ng-options dynamically at run-time based on the "display" and "value" parameters that I am passing to the directive. You can see that in the "pre:" linking function inside the directive. Now, I know that this is not working because at the time this function is being executed I do not have the scope values. However, I cannot do this in the post: linking because that would be too late for the ng-options expression. Is there a way to achieve this functionality or am I totally barking up the wrong tree here? Thank you so much in advance.
Never mind. I used the following code in the template:
<div class="row form-group form-horizontal">
<label data-for="id" class="control-label col-md-3">{{label}}</label>
<div class="col-md-9">
<select data-id="id" data-name="name" data-ng-disabled="disabled" class="form-control"
data-ng-model="model"
data-ng-options="o.{{value}} as o.{{display}} for o in options" data-ng-required="required" compile>
<option></option>
</select>
</div>
That, and I took whatever code I had originally put in the pre: linking function inside the directive.
This is my HTML:
<input id="email" type="text" name="email" class="form-control" ng-
model="user.email" required ng-pattern="/^[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\[A-
Za-z]{2,4}$/" input-tooltip>
And my directive:
angular.module('app')
.directive('inputTooltip', function($timeout, $compile) {
return {
restrict: 'A',
require: ['^form', 'ngModel'],
link: function(scope, element, attrs, controllers) {
var formCtrl = controllers[0],
ngModelCtrl = controllers[1];
function trigger() {
$timeout(function() {
element.trigger('manual');
}, 0);
};
var name = element[0].name;
attrs.$set('tooltipTrigger', 'manual');
attrs.$set('tooltipPlacement', 'top');
attrs.$set('tooltipEnable', formCtrl.$name + '.' + name + '.$invalid');
attrs.$set('tooltip', 'Invalid Email');
ngModelCtrl.$viewChangeListeners.push(trigger);
$compile(element.contents())(scope);
}
};
});
It seems to create the right HTML:
<input id="email" type="text" name="email" class="form-control ng-valid-
required ng-dirty ng-valid-parse ng-invalid ng-invalid-pattern ng-touched" ng-
model="user.email" required="" ng-pattern="/^[A-Za-z0-9._%+-]+#[A-Za-z0-9.-
]+\.[A-Za-z]{2,4}$/" input-tooltip="" tooltip-trigger="manual" tooltip-
placement="top" tooltip-enable="form.email.$invalid" tooltip="Invalid Email">
The attributes are there and the trigger() function runs on input change, but no tooltip is shown.
Anything you find I'm doing wrong or could be doing better — I'm feeling there are some noob things in there — please let me know!
Thanks.
I have the following Angular directive:
app.directive('basicInput', function () {
return {
restrict: 'AE',
templateUrl: 'DirectiveTemplates/BasicInput.html',
replace: true,
scope: {
ngModel: '=',
visual: '#',
placeholder: '#',
pattern: '=',
ngChange: '='
}
};
});
With the following Template:
<ng-form name="basicInput">
<div class="form-group">
<label for="input">{{visual}}</label>
<input type="text" class="form-control" name="input" ng-model="ngModel" placeholder="{{placeholder}}" required ng-pattern="pattern">
<div ng-messages="basicInput.input.$error" class="help-block">
<span ng-message="required"> Required</span>
<span ng-message="pattern"> Invalid Characters or is too short</span>
</div>
</div>
</ng-form>
Which I call in html as (for example):
<basic-input ng-model="formData.official_name" data-visual="Official Name" data-placeholder="Name" pattern="regex.short"></basic-input>
My Question is, how can I make the 'required' on the input tag from the template optional?
Try this:
Directive:
scope: {
ngModel: '=',
visual: '#',
placeholder: '#',
pattern: '=',
ngChange: '=',
isRequired: '='
}
Template:
<input type="text" class="form-control" ng-required="isRequired" name="input" ng-model="ngModel" placeholder="{{placeholder}}" ng-pattern="pattern">
Usage:
<basic-input ng-model="formData.official_name" is-required="false" data-visual="Official Name" data-placeholder="Name" pattern="regex.short"></basic-input>
ngRequired
you can set ng-required attribute to true or false ,, according to an attribute
docs : https://docs.angularjs.org/api/ng/directive/input
I am trying to implement Change Password feature in MVC (Rest server) application from the User Control Panel but because of some strange reason I can't scope values from form input.
My html form:
<accordion-group heading="Change password" is-open="changePasswordStatus.open" style="cursor: pointer">
<div>
<div>
<form class="form-horizontal" role="form">
<form-row model="newPassword" name="New: " size="col-sm-8"></form-row>
<form-row model="repeatedNewPassword" name="Repeat: " size="col-sm-8"></form-row>
<form-row model="currentPassword" name="Current: " size="col-sm-8"></form-row>
<br>
</form>
</div>
<div>
<button class="btn btn-default btn-sm" ng-click="changePassword()">Save</button>
<button class="btn btn-warning btn-sm" ng-click="changePasswordStatus.open = !changePasswordStatus.open">Cancel</button>
</div>
</div>
</accordion-group>
My formRow.html:
<div class="form-group">
<label for="inputText3" class="col-sm-2 control-label">{{name}}</label>
<div class="{{size}}">
<input type="{{type}}" class="form-control" data-ng-model="model">
</div>
</div>
My formRow.js:
collectionsApp.directive('formRow', function(){
return {
restrict: 'E',
replace: true,
scope: {
model: '=',
name: '#',
size: '#',
type: '#'
},
templateUrl: '/directives/formRow.html',
link: function(scope, attrs, element) {
}
}
});
My userController:
$scope.changePassword = function() {
if ($scope.newPassword === $scope.repeatedNewPassword) {
userService.changePassword($scope.newPassword, $scope.currentPassword);
} else {
$scope.alerts.push({
msg : 'Passwords do not match!'
})
}
}
And when I enter values in inputs and place breakpoints and trigger changePassword() in debug i get:
If condition has passed with value of true because they are both undefined.
I believe this may be the case of prototypical inheritance and scope, requiring an object being passed into your scoped parameters. Mind trying to change your parent scope to use an object and bind to the properties and not the primitive values:
$scope.security = {newPassword : '', currentPassword = ''};
then you would use something like this in your attributes:
model="security.newPassword"
Or better yet, not make it confusing with model:
myapp-model="security.newPassword"
or pass in the whole object
myapp-security="security"
Working in this plunker template ?
<form ...>
<form-row model="newPassword" name="New: " size="col-sm-8" required ></form-row>
<form-row model="repeatedNewPassword" name="Repeat: " size="col-sm-8" required ></form-row>
<form-row model="currentPassword" name="Current: " size="col-sm-8" required ></form-row>
</form>
I'm having a problem with AngularJs. I have created a directive that $watch the model and it takes some action based on the model's current status. However, although during debugging I can see that the $watch is set, it is only being triggered after the model get valid at least once and I don't know why that is happening. Debugging it doesn't even gets into the $watch function when something is typed.
The code is below:
Directive:
(function() {
'use strict';
var app = angular.module('app');
app.directive('tooltipValidation', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
var tooltip = $(element).qtip({
content: {
text: element.next('div')
},
show: false,
hide: true
}).qtip('api');
scope.$watch(attrs.ngModel, function() {
if (ngModel.$invalid && ngModel.$dirty) {
tooltip.show();
} else {
tooltip.hide();
}
});
}
};
});
})()
HTML:
<div class="form-address clearfix" ng-show="isNewShippingAddress" ng-form="newShippingAddressForm">
<h3>Include new shipping address:</h3>
<div class="novo-endereco clearfix" id="newAddress">
<div class="required address apelido">
<label for="newShippingAddressAlias">Alias</label>
<input id="newShippingAddressAlias" name="newShippingAddressAlias" type="text" tooltip-validation ng-model="newShippingAddress.Alias" required ng-maxlength="32" />
<div data-ng-show="newShippingAddressForm.newShippingAddressAlias.$dirty && newShippingAddressForm.newShippingAddressAlias.$invalid">
<p data-ng-show="newShippingAddressForm.newShippingAddressAlias.$error.required">obligatory</p>
<p data-ng-show="newShippingAddressForm.newShippingAddressAlias.$error.maxlength">max 32 char</p>
</div>
</div>
<div class="required endereco">
<label for="newShippingAddressStreet">Street</label>
<input id="newShippingAddressStreet" name="newShippingAddressStreet" type="text" tooltip-validation ng-model="newShippingAddress.Street" required ng-maxlength="256" />
<div data-ng-show="newShippingAddressForm.newShippingAddressStreet.$dirty && newShippingAddressForm.newShippingAddressStreet.$invalid">
<p data-ng-show="newShippingAddressForm.newShippingAddressStreet.$error.required">obligatory</p>
<p data-ng-show="newShippingAddressForm.newShippingAddressStreet.$error.maxlength">max 256 char</p>
</div>
</div>
<div class="required cep">
<label for="newShippingAddressZipCode">ZipCode</label>
<input id="newShippingAddressZipCode" name="newShippingAddressZipCode" type="text" tooltip-validation ng-model="newShippingAddress.ZipCode" required ng-pattern="/^[0-9]{8}$/" />
<div data-ng-show="newShippingAddressForm.newShippingAddressZipCode.$dirty && newShippingAddressForm.newShippingAddressZipCode.$invalid">
<p data-ng-show="newShippingAddressForm.newShippingAddressZipCode.$error.required">obligatory</p>
<p data-ng-show="newShippingAddressForm.newShippingAddressZipCode.$error.pattern">8 digits</p>
</div>
</div>
<input type="submit" class="button grey" value="Save new address" data-ng-click="saveShippingAddress()" ng-disabled="newShippingAddressForm.$invalid" />
</div>
</div>
Regards,
dimello
Try:
scope.$watch(function(){
return ngModel.$viewValue; //Watch for view value (the value in your input)
}, function() {
if (ngModel.$invalid && ngModel.$dirty) {
tooltip.show();
} else {
tooltip.hide();
}
});
DEMO
Explanation:
When you type an invalid value into the input with ng-model, the underlying model is not updated, causing your scope.$watch(attrs.ngModel not being fired because you're watching for changes in the model. If you need to fire the function every time the input changes no matter it's valid or not, try the above solution.