Angular form with dynamic name are not initializing - angularjs

I have a few objects and a form. Each object should remember the state of it's form (mainly, dirtyness).
I'm trying to create a form with a dynamic name like such:
<form name="selectedObject.form">
<input type="text" name="name" ng-model="selectedObject.name" required>
</form>
My problem is:
I make the first form dirty
Change the selected object
The form is considered dirty
I would think the using a dynamic name to the form would set a watch and have it rerender dynamically.
Anyway to do this?
Here's a plunkr simulating the problem:
http://plnkr.co/edit/NAHVfhCf6RhpJHPGl7El?p=preview

As you would like to have it work, I think not. I also see problem in your code, namely form declaration. Name is string so now your form's name is always literal selectedObject.form. I think you ment to write it as <form name="{{ selectedObject.form }}"> and have actual name for the form instead of {} you have assigned now?
You could add isDirty as new property to your objects and toggle it manually.
$scope.objects = [{
name: 'Object1',
type: 'Type1',
form: 'form1',
isDirty: false
},{
name: '',
type: 'Type2',
form: 'form2',
isDirty: false }];
<body ng-controller="MainCtrl">
<button ng-click="setSelected()">Change selected</button>
<form name="{{ selectedObject.form }}">
<input type="text"
ng-model="selectedObject.name"
ng-change="selectedObject.isDirty = true">
{{ selectedObject.isDirty }}
</form>
</body>

Related

Angularjs difference between fetched and locally modified data

I fetch data from an API and it gives my something like this:
{id: 1, name: ''}
The field name is ng-model for an input field.
As soon as I write something in the field, the json object I have a reference to, will have name equals to something else than empty.
That's normal behaviour.
However, if Im interested in knowing if name "was" empty when I fetched data, can I do this in a simple way? Without needing to create new variables?
Basically I want to have 2 ng-if elements and only display one of them. But I cannot trust the data in the object because I don't know if the name-field has been changed locally or on the server:
<input type="text" ng-model="ctrl.name" ng-if="ctrl.name === ''" />
<span ng-if="ctrl.name !== ''">{{ctrl.name}}</span>
Use can the $dirty (this docs are about form but it's true for inputs as well) prop of an input in form so the logic will be: show the input if the name is not defined (undefined or an empty string) or when the input is dirty - means the user typed in the input. And the opposite for the span. This way you'll not have to hold another param.
angular.module('app', []).controller('myController', function() {
// comment this line to simulate name was empty
// this.name = 'text from server';
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="myController as ctrl">
<form name="myForm">
<input type="text" name="name" ng-model="ctrl.name"
ng-if="!ctrl.name || myForm.name.$dirty" />
<span ng-if="!!ctrl.name && !myForm.name.$dirty">{{ctrl.name}}</span>
</form>
</div>
</div>

Angularjs placeholder not showing when dynamically generate textbox

I am generating a dynamically text boxes using angularjs. I set a array in controller and repeating in view with ng-repeat. Here is controller code :-
this.total_options = [
{text : 'form.options.Option1' , placeholder: 'Enter Option Here'},
{text: 'form.options.Option2', placeholder: 'Enter Option Here' }
];
Now in view i am repeating this options like :-
<li data-ng-repeat="option in mcssController.total_options">
<input required="required" type="text" ng-model="option.text" class="option" placeholder="{{option.placeholder}}" />
</li>
But when page is rendered the textbox showing ng-model property 'form.options.optoin1' instead of placeholder('Enter Option Here'). How can i solve this problem ?
See if you clear out the form, you should be able to see the placeholder!
Try:
<li data-ng-repeat="option in mcssController.total_options">
<input required="required" type="text" ng-init="model=$eval(option.text)" ng-model="model" class="option" placeholder="{{option.placeholder}}" />
</li>
You want ngModel to bind to a model, not a property that represents a string. Since you want to interpret the string as a model, you can use $scope.$eval. It should work if you use $scope.$eval in an ngInit expression, and then use result to bind to ngModel.

set input text field from combobox using angularjs

I want to set a input text field of formular from JSON object, which is value of select option. I have a data in AngularJS controller, after selecting combobox, data is changed, but text field doesn't be filled.
https://github.com/lijunwu001/jstree_with_select.git
Here is demo link on github.
In general it's wrong approach. To see your error you can change your code from
<div ng-repeat='node in vm.selected'>
ID: <input type='text' ng-attr-value='{{ node["id"] }}' />
Description: <input type='text' ng-attr-value='{{ node["text"] }}' size='35'/><br />
</div>
To:
<div ng-repeat='node in vm.selected track by $index'>
Just symbol: <input type='text' ng-attr-value='{{ node }}' />
</div>
It looks strange, doesn't it? It's because you cant bind object to "select" like
<select ng-model='vm.selected' required>
After your click on "select" option your value of vm.selected is just string, but not an object. And you are doing ng-repeat with symbols of this string.
You could use the ng-change directive

Dynamic Form and AngularJs

We have a dynamic Form being rendered based on database configurations. I am using code as mentioned in the below fiddle
But am not able to get the value of the checkbox element selected. Please guide me through this.
I am using checklist-model for Checkbox Elements.
<label ng-repeat="cCheck in form.color">
<input type="checkbox" checklist-model="outputs[form.databaseAttr]" checklist- value="cCheck" ng-init="outputs[form.databaseAttr] = form.defaultValue"> {{cCheck}} <br>
</label>
Fiddle Link
Please let me know if we have anybetter way of handling Dynamic Forms. Something like jQuery Serialize where we pass the formId and get all elements from the form.
There is a checklist-directive developed to solve the checkbox problem. You can download check-list.js and add it as the module dependency as following:
var exampleApp = angular.module('example', ["checklist-model"]);
So, in your html, you should use checklist-model and checklist-value instead of ng-model and ng-value respectively:
<div ng-switch-when="checkbox">
<br>{{form.text}} <br>
<label ng-repeat="cCheck in form.color">
<input type="checkbox" checklist-model="outputs[form.databaseAttr]" checklist-value="cCheck" ng-init="outputs[form.databaseAttr] = form.defaultValue"> {{cCheck}} <br>
</label>
</div>
Try it yourself.
EDIT: In order to set default values of the checkbox, you can put the values that you want into the outputs[from.databaseAttr] array. In your case, defaultValue:
{
text: 'select mutiple colors',
databaseAttr: 'checkbox',
type: 'checkbox',
color: ['red', 'blue', 'black'],
defaultValue: ['blue'] // <-- blue is set as default
}
JsFiddle.

Have AngularJs update {{binding}} as the user types in input[email]

Angular only updates the model from an input[email] after the user has entered a valid email address. How can I add a {{binding}} somewhere on the page that will update with the email value as the user types -- even before the user has typed in a valid email address?
Here's what I've tried so far:
<div ng-app>
<div ng-controller="MyCtrl">
<form name="MyForm" novalidate>
Name: <input type="text" name="name" ng-model="contact.name" /><br/>
Name as you type: {{contact.name}}<br/>
Email: <input type="email" name="email" ng-model="contact.email" /><br/>
Email as you type: {{contact.email}} (doesn't work)<br/>
Also doesn't work: {{$document.forms.MyForm.elements.email.value}}
</form>
</div>
</div>
Controller:
function MyCtrl($scope) {
$scope.contact = {};
}
(fiddle)
The name updates in real-time like I want, but the email doesn't.
I'd like to leave the email validation enabled. I just need some way to bind the un-validated input[email] text, so it updates as the user types.
Update 2014/7/8
I'd like to add an explicit requirement that the type="email" remains unchanged. I do not want to change the semantics of the markup to workaround a limitation of the framework. If need be, I'd rather pull in a complementary dependency (such as jQuery) to shim in the needed functionality.
I'm not opposed to handling validation in the controller — as suggested by rageandqq and charlietfl — if it could be done easily. Looking around though, it looks like it could be tricky (given my requirements).
That is how angularjs works. If you use <input type="email" /> angular is not going to bind your input till input will be valid in this case value must be a proper e-mail address.
please read more here : https://github.com/angular/angular.js/issues/1426
The workaround I've come up with so far is to use jQuery to listen for the input change and update an object on $scope that I've called formRaw. It works. Still, I'm hoping someone will come along and show me a better way.
The updated example:
<div ng-app>
<div ng-controller="MyCtrl">
<form name="MyForm" novalidate>
Name: <input type="text" name="name" ng-model="contact.name" /><br/>
Name as you type: {{contact.name}}<br/>
Email: <input type="email" name="email" ng-model="contact.email" /><br/>
Email Model: {{contact.email}}<br/>
Email Form: {{formRaw.email}}
{{q}}
</form>
</div>
</div>
And controller:
function MyCtrl($scope) {
$scope.contact = {};
$scope.formRaw = {};
$('input[type=email]').on('keyup change', function () {
var input = $(this);
$scope.formRaw[input.attr('name')] = input.val();
$scope.$digest(); // FIXME: there's got to be a better way
});
}
(fiddle)
The type="email" attribute on your E-mail input is what is causing the DOM binding to mess up.
Changing it to type="text" works allows your {{contact.email}} to display correctly.
Edited JSFiddle.

Resources