ng-messages aren't displayed in custom directive - angularjs

I created a custom directive which is used to access the id of the form, to display messages if same validation failed.
directive Code
<div>
<md-input-container>
<label class="inputLabel" translate>amount</label>
<input ng-model="order.amount" name="amount" type="text" required
max="availableAmount"
ng-disabled="disabled" ng-currency flex/>
<ng-messages flex for="dataForm.amount.$error" ng-if="dataForm.amount.$dirty">
<ng-message when="max">max reached</ng-message>
</ng-messages>
</md-input-container>
</div>
usage:
<form id="dataForm">
<custom-directive></custom-directive>
</form>
It seems like I can not access the form. Or angularmessage can not handle the different scoping.
Has anyone the same problem or an idea?
Thank you
fyi.: I have found the following post, but I didn't think that i have the same problem as that guy.
angularjs ngMessages inside directive
I use Angular 1.4.8;message 1.4.8 and angular material 1.0.4

If directive have an isolated scope, than it will not be able to access the form controller object of the ng-form directive.
Angular enables multiple canonical forms, so you can simply wrap your input inside of your directive with a form / ng-form.

Related

ngMessages with Angular 1.5.x Component

I just tried introducing ngMessages into my app that's using Components that were added in 1.5. As soon as I include any reference to ngMessage in my template I'm receiving this error message:
Error: $compile:ctreq Missing Required Controller.
This is a common error with ngMessages and the normal remedy is
suggested here:
https://docs.angularjs.org/error/$compile/ctreq?p0=ngMessages&p1=ngMessage
However, I'm using components, which are a special type of directive and this doesn't appear to be an option for components.
Has anyone gotten ngMessages to work within a component in 1.5?
The syntax for use with a directive is like this:
myApp.directive('myDirective', function() {
return {
require: 'ngModel',
...
}
}
The component documentation: https://docs.angularjs.org/guide/component doesn't cover an equivalent to require.
This might help you.
<form name="userLoginForm" autocomplete="off">
<input type="text" minlength="10" maxlength="10" ng-pattern="/^[0-9]+$/" required ng-model="userData.mobileNumber" placeholder="Enter Mobile Number" class="form-control login-form-input" id="mobileNumber" name="mobileNumberInput"/>
<div ng-messages="userLoginForm.mobileNumberInput.$error" role="alert">
<div ng-message="required">
This field is required
</div>
<div ng-message="pattern">
Enter correct mobile number
</div>
<div ng-message="minlength, maxlength">
Your mobile number must 10 characters long</div>
</div>
</div>
It happens when you don't have correct div structure.
First div has to include ng-messages, and one inside should be ng-message.
From Documentation:
<ANY **ng-messages**="expression" role="alert">
<ANY **ng-message**="stringValue">...</ANY>
</ANY>
Angular's debug message is unhelpful in this instance and cause more confusion.

angularjs xeditable and angularjs ui-tinymce together in an editable form

Is the a way to make a textarea ui-tinymce part of and an editable-form?.
I found a workaround by making ng-model of the editable-textarea and textarea ui-tinymce the same and then I hide the editable-textarea.
<form
onaftersave="onsave({$data:$data})"
editable-form
name="forms.{{formName}}"
>
<textarea ui-tinymce="tinymceOptions"
name="desccomp"
ng-model="item.desccomp">
</textarea>
<div
e-ng-show="false"
editable-textarea="item.desccomp"
e-name="desccomp"
>
</div>
</form>
Actually, TinyMCE already has inline abilities
https://www.tinymce.com/docs/demo/inline/
I'm facing same issue and thinking I'm gonna use only tinyMCE (with angular-ui-tinymce) leaving xeditable for this case).

Error: No controller: ngModel for Angular Typeahead

I have a mix of Jquery and angular and I'm trying to display a dialog with a Typeahead inside.
For objective reasons, I display a modal body and appended it with the Angular typeAhead directive.
$('.modal-builder .modal-body').append('<input type="text" placeholder="Start typing product title" typeahead="item.title for item in getAutoCompleteProducts($viewValue)" typeahead-loading="loadingLocations" class="form-control input inline" typeahead-wait-ms="200" typeahead-min-length="0" typeahead-on-select="insertProduct($item)" /><i class="fa fa-spinner fa-spin fa-lg" ng-show="loadingLocations" > </i>');
after this I try to compile it:
var cr = $('.modal-builder .modal-body').append('<div class="row"></div>');
$compile(cr)(scope);
But I'm getting this error:
Error: No controller: ngModel
The scope is also from a Angular Bootstrap dialogue directive. Inside it I have various buttons to display the dialogue with the TypeAhead.
I read other questions on Stack and looks like an error between the scopes of the directives. I could not solve it by doing separate scopes.
Should it be compiled in a complete new scope?
Add ngModel directive to your typeahead template:
<input type="text"
ng-model="product.selected"
placeholder="Start typing product title"
typeahead="item.title for item in getAutoCompleteProducts($viewValue)"
...
But such a mix of jQuery with Angular is not a very good idea.

Required field Angularjs 1.2 and Bootstrap 3

With the changes to angularjs and bootstrap 3 I have been unable to create a form field that's required where the item will be surrounded with red highlight by only adding the required parameter to the input field. Here is a plunker with how I have it setup on my system and would expect it to work. I can't seem to find any documentation on bootstraps site about required either so that would really help if anyone can find that.
Plunker
EDIT: Replaced all the following with below comments ideas... I would still like a solution where I don't need to write any css and use Bootstrap 3.
My form field looks like this:
<body ng-app>
<div ng-controller="Controller" class="container">
<form novalidate class="simple-form" name="myForm">
<div class="form-group col-sm-4">
Name: <input type="text" ng-model="name" name="name" class="form-control" required/>
E-mail: <input type="email" ng-model="email" name="email" class="form-control" required/>
<small class="error"
ng-show="myForm.email.$error.required">
Your name is required.
</small>
</div>
</form>
</div>
</body>
Script.js Looks like this:
function Controller($scope) {
$scope.name = "Test";
$scope.email = "";
}
Style.css looks like this:
input.ng-invalid {
border: 1px solid red;
}
While this works it replaces the bootstrap css with the css above. I would much prefer to simply add in required to an element and not have to rewrite the css to add the hue and the animation.
I agree with both of the other two answers but would like to add more
I think your main problem is that Bootstrap 3 removed styling based on the :invalid and related pseudo-classes (see here for why). This is where the red outline in bootstrap 2.x came from.
Firstly, to fix your plunker you should:
Bootstrap your app with ng-app as Mike says
Put your input in a form with novalidate
Give a model to your input with ng-model so that it can be invalidated (by angular, using classes)
Move jQuery script include before bootstrap as it is a requirement of bootstrap.
Now you have a plunker where the correct classes are applied to indicate input validity. You won't yet have styling on these, but they won't depend on your browser's HTML5 form validation, so will work in anything angular supports.
To apply styling, you can either use straight CSS and apply it to the ng-valid, ng-invalid, ng-invalid-required etc classes, or you can use the ng-class suggestion from this comment to apply bootstrap's classes when you need them
ng-class="{'has-error': formname.inputname.$invalid}"
if you have named your input and wrapped it in a control.
Updated plunker: http://plnkr.co/edit/mE3dkG?p=preview
Edit
I had a go at making a directive for this too. It may be overkill, but this should work wherever you have a form-group class and add an ng-form to the same element
.directive('formGroup', function(){
return {
restrict: 'C',
require: '?form',
link: function(scope, element, attrs, formController){
if(!formController)
return;
scope.$watch(function(){
return formController.$valid;
}, function(valid) {
if(valid)
element.removeClass('has-error');
else
element.addClass('has-error');
});
}
};
});
Yet another plunker: http://plnkr.co/edit/UQjRrA?p=preview
* The email will not be valid unless it looks like an email
You have a couple of things missing here. First, in order for a form field to validate it needs a unique name:
<input class="form-control" type="text" name="test" required/>
Second, in order to disable stock HTML5 validation, you need to add a novalidate attribute to the form:
<form class="form-horizontal" name="myForm" role="form" novalidate>
Third, and most importantly, your example has no app or controller associated with it, so angular is completely ignoring it. That one you have to fix yourself.
Read more about angular forms here: http://docs.angularjs.org/guide/forms
I suggest you this excellent step by step : http://www.ng-newsletter.com/posts/validations.html

How to prevent transcluding directive to create new child scope for the form directive?

I have a problem with directive transclude and the form directive. As you may know, the form will end up in the "scope" if you add the "name"-property to the form tag, then you can check for form validation and so on.
My problem start when i put the form tag in a directive that uses transclude. I'm aware of how to deal with this problem with two-way data binding, as mention here https://stackoverflow.com/a/14484903/1029874 -- "use an object instead of a primitive"
But my form ends up in the transcluding directives scope. Here is an example of what i want to do.
<div ng-controller="appCtrl">
<widget>
<widget-header>{{model.property}}</widget-header>
<widget-body>
<!-- The form will end up in "widget-body":s scope instead of appCtrl:s scope -->
<form name="appForm" ng-submit="submit()">
<input type="text" required ng-model="model.property" />
<input type="submit" value="submit" />
</form>
</widget-body>
</widget>
</div>
And here is the fiddle, http://jsfiddle.net/WLksJ/1/
Is there a way that I can get around this behavior?
Thanks!
An interesting question, but a problem that's easily avoided by using
<form name="appForm" ng-submit="submit(appForm.$valid)">
and checking the parameter in the submit function.
http://jsfiddle.net/udMJ7/
Another (perhaps better) option is to use this which is set to the scope of the last controller (in this case the form controller, which we want)
$scope.submit = function(){
if(this.appForm.$valid){
//post the form!!
}
};
http://jsfiddle.net/udMJ7/1/

Resources