angular ng-model transclude transfer - javascript

I am trying to create custom elements which will convert my form elements to match bootstrap's form styling structure
Basically,
<my-input ng-model="myname">
should become
<div class="form-element">
<input ng-model="myname" />
</div>
The problem is that when I use transclude, the ng-model goes to the root element and the resulting DOM is
<div class="form-element" ng-model="myname">
<input>
</div>
Is it possible to choose which inner element the ng-model attribute is transferred to??
If I create another directive called my-model and use it instead of ng-model, how can I transfer this to the inner input element?
<my-input my-model="myname">
should become
<div class="form-element">
<input ng-model="myname" />
</div>

I think it is unnecessary to use ng-transclude here, you can simply have directive
<my-input model="myname">
and directive template
<div class="form-element">
<input ng-model="model" />
</div>
where directives scope is
scope: {
'model': '='
}
By using this you can have couple of models in directive and you can put them wherever you want.

Yes. I ran into this issue a little while ago.
You need to bind your ng-model as a property of an object such as.
<div class="form-element">
<input ng-model="user.myname" />
</div>
And in controller, make sure you do this.
$scope.user = {};
In this way, angular would be able to find the ng-model.

Related

Angular1: How to reflect ng-model errors on another element?

I have a directive with the following template
<div>
<span class="label">My Label</span>
<input ng-model="name" required>
</div>
I want the label to be painted red when the input field is invalid.
How can I do that?
Currently I have another directive to sync all the errors from ngModelCtrl to the wrapping div
<div add-all-errors>
...
</div>
And the directive's link function does something like this:
const ngmodel = $element.find('[ng-model]').controller('ngModel');
$scope.$watch(()=>ngmodel.$error, addAllClasses, true);
Where addAllClasses simply makes sure the correct classes appear on the element..
I also tried just adding the same ng-model
<div ng-model="name">
...
</div>
But did not see the classes there..
any better way to do this?
This is why we use the angularjs form... I'm really not sure why people are against using a very handy feature.
I've made a plunker for you.
https://plnkr.co/edit/bGOcQjWzlRq2aTYZUYNm?p=preview
<form name="form">
<span ng-class="{red: form.name.$invalid}">Name:</span>
<input name="name" ng-model="name" required>
</form>
A little more insight of what's going on. form is added to the scope auto magically by angularjs by it's name. In this case, I named it form, however it can be any name.
Now form is an ngForm Object and adds all input field into it by their name attributes. This way we can do form.name to get another object similar to the ngForm Object. We can then use $invalid or $valid properties with ng-class.
ngForm is pretty powerful and is loaded with many cool properties and methods. Just call console.log(scope.form); You will need to put in a method and add it to ng-change to see updates.

ngMessages not working correctly with nested input

I have an input field that is nested within another <div> element, and I am trying to use ngMessages on that inside input field, but I can't seem to get it to validate correctly.
<div class="form-group" ng-model="object.idnumber" ng-hide="condition.userObjectsHidden">
<label class="form-control-label col-lg-12">ID Number</label>
<div class="col-lg-12">
<input type="text" name="idnumber" placeholder="111001111"
ng-model="user.idnumber"
ng-pattern="idpattern"
class="form-control input-lg"
required="required"></input>
<div ng-messages="idnumber.$error" ng-if="idnumber.$dirty">
<p ng-message="pattern">You are wrong!</p>
</div>
</div>
</div>
I'm not sure if it matters in terms of functionality where the <div ng-messages...> tag is, but I have also tried having it completely outside of this element with the same results. If I understand Angular and ngMessages correctly, I need to assign ng-messages to a directive--$error in this case--that I get to by dot-walking across name assignments. As far as I know, I have done this with idnumber.$error, although to be fair, I have also tried a more extensive dot-walk by using kiosk-form.uin.$error, where kiosk-form is the name of the entire form.
I have tried both ng-message="pattern" as well as ng-message="required". Also, just for clarity, idpattern is defined in my Javascript file as a regex string. It is defined correctly.
Rename your form as kioskFormand then ng-messages ="kioskForm.idnumber.$error"

Angular directive automatically move attributes to inner template element with replace

When creating an angular directive with replace: true then the HTML in the DOM is going to be replaced with your template HTML. The attributes will then be put on the element that is going to replace your element.
e.g.
<input type="text" name="myName" my-directive>
will become something similar to
<div name="myName" my-directive>
<input type="text">
</div>
when my template of the myDirective directive looks like
<div>
<input type="text">
</div>
Now the question is how can I achieve that the name attribute is not set on the div but on the inner input element?
I could do it manually by be removing the attributes from the parent div element and add them to the input element. But I asked my-self whether there would be an automated way to do this with an option for angular directives.

How to pass directives to an element in the directives template in AngularJS?

I have a directive called step-field, in the template of the directive i have input or select elements that should sometimes have max-length or ng-required or some custom directive like validate-username.
The step field looks like this:
<step-field parent="Admin" field="Username"></step-field>
I want to add "validate-username" and "required=true" to this directive so it will look like this
<step-field parent="Admin" field="Username" validate-username required="true"></step-field>
And in the inside of the directive template i want the validate-username and required to be passed to the input field.
(btw $scope.isRequired = attrs.required)
<div class="field">
<label> {{fieldName}}:</label>
<input
name="{{inputName}}"
ng-model="wizard[modelName][fieldNameCamel]"
ng-required="{{isRequired}}"
type="{{inputType}}"/>
<div class="field--required" ng-if="isRequired===true"> * </div>
<div class="ng-messages__wrap"
ng-show="wizardForm[step][inputName].$dirty || wizardSubmittedOnce">
<div ng-messages="wizardForm[step][inputName].$error"
ng-messages-include="/templates/error-messages.html"></div>
</div>
</div>
How can i apply some of the directives i pass to step-field to the input field in the template?
Thanks!

Error: [$compile:multidir] Multiple directives [form, form] asking for 'form' controller on: <form ng-form="">

I am getting this error on a form I am building in angularjs.
`Error: [$compile:multidir] Multiple directives [form, form] asking for 'form' controller on:
<div data-ng-controller="shortlistController">
<ul>
<li data-ng-repeat="job in jobs">
<div>{{ job.role }}</div><div>{{ job.salary }}</div><div>{{ job.company }}</div>
</li>
</ul>
</div>
<form ng-form>
<input type="text" ng-model="newRole">
<input type="text" ng-model="newSalary">
<input type="text" ng-model="newCompany">
<input type="text" ng-model="newUrl">
<button>Submit</button>
</form>
Initially I had the form within data-ng-controller, I took it out to see if the controller might have been the issue..
Please ask if you think I need to post more code, I am using angulars native routing system
Each of these is more or less identical and refers to the form directive:
<form></form>
<div form></div>
<div x-form></div>
<div data-form></div>
So you can do either <div form></div> or simply <form></form>, and in both cases they refer to the same form directive. But <form form></form> would be redundant.
The ngForm directive which you mention is actually an alias for the form directive above, and can be referenced using any of these:
<ng-form></ng-form>
<div ng-form></div>
<div x-ng-form></div>
<div data-ng-form></div>
So in your case, you were doing <form ng-form></form>, which is really the same as <form form></form>, which is why you're getting that error.
This page explains in more detail all the different ways to reference directives:
http://docs.angularjs.org/guide/directive
BTW, a benefit (sometimes) to using the <div ng-form></div> format is that you can do nested forms, whereas you can't do nested forms using just the <form> tag.
You don't need the ng-form if you're using <form> as it automatically is hooked up to the ng-form directive. You use either or, not both.
I encountered the same problem when I set my component name to form.
angular.module("testApp").component("form", {
...
});
Effect was the similar as in #user553086 answer. Change component's name solves the problem.

Categories

Resources