I have a form which contains two input fields, I want to sync the next input field when user is typing in the first input field by default, and user can edit the second field as they like, below code works fine:
<input type="text" ng-model="name">
<input type='text' value='{{name}}'>
<button ng-click='submit()'>submit</button>
However, to be able to get the value of second field, I need to put ng-model to the second field, and once I put ng-model, it won't sync anymore.
This is the example
How should I get the second field's value if I don't put a ng-model to it.
Thank you.
You can use ng-change. When user changes input 1 the ng-change method will be called and input2 will be updated .but when user change input 2 nothing will be called .
<DIV ng-app='app'>
<form ng-controller='myController'>
<input type='text' ng-model='name' ng-change="callMe()"/>
<input type='text' ng-model="name2" />{{name2}}
</form>
</DIV>
and controller js
var app = angular.module('app', []);
app.controller('myController', function($scope){
$scope.callMe =function(){
$scope.name2=$scope.name;
}
//$scope.name
//$scope.name2
})
update fiddle example
You could use the $scope.$watch Method for your needings.
I have updatet your fiddle.
What i did is easy, everytime the model changes, the $watch will be called with the new value of the model, then you just need to copy the value into the second model.
First approach that came to my mind was to ng-bind a property with a setter that would do what you want:
<input type='text' ng-model='nameModel' />
then
app.controller('myController', function($scope) {
Object.defineProperty($scope, 'nameModel', {
get: function() { return $scope.name1; },
set: function(x) { $scope.name1 = $scope.name2 = x; }
});
});
This causes any edit to nameModel to affect both name1 and name2.
Fiddle
You could do a similar wrapper around name2 to track whether it has ever been modified (dirty/pristine), and have nameModel only change scope.name2 if it is pristine.
Fiddle with better user experience
(If you're using Angular forms, it tracks the field status for you, so you could directly look at form.name2.$pristine.)
It seems that what you need is to set the value to the scope variable.
So your code would then look like this:
<input type="text" ng-model="name">
<input type='text' value="{{name}}" ng-model="somethingelse">
<button ng-click='submit()'>submit</button>
Hope that helps.
Related
I am looking for a solution on passing data from a specific input text field to AngularJS. it may be a Javascript variable too. If the variable is changed from inside a javascript code it is not updating on AngularJS side. If i take the same variable and in the text field add at least one character or modify something i see variable updating and everything working as it should.
I tried something with angular.element(document.getElementById('ControllerElementID')).scope().funct(); but still no luck. When i update at least one field from the keyboard, all text fields that are related to "ng-model="sig.sigBase6422"" are updating properly as it should. If i call this updates through a JavaScript function i see updates only on specific text field and no updates at all on ng-model happening. How to make it updating as simple as possible? Below i will post a small example. I was able to store data from variable to a external file and in AngularJS read it from file and use it. this is way too long, complicated and ridiculous. I am sure there should be a better way.
Thank you!
<script type="text/javascript">
function addtext1() {document.getElementById("myID1").value = "1111111111111111";}
function addtext2() {document.getElementById("myID2").value = "2222222222222222";}
</script>
<div>
<form action="#" name="FORM1">
<TEXTAREA NAME="sigData" ng-model="sig.sigBase6422" ROWS="10" COLS="20">String: </TEXTAREA>
</form><br>
<input type="text" name="myID1" id="myID1" ng-model="sig.sigBase6422" ><br>
<input type="text" name="myID2" id="myID2" ng-model="sig.sigBase6422" ><br>
<p>Value {{sig.sigBase6422}}!</p>
</div>
<!-- test field -->
Add text 1
Add text 2
Indeed if you want to use AngularJS for what it was created, you have to rewrite your code completely using directive or controller. You variables and functions accessible from the view should be attached to the $scope too.
var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", function($scope){
$scope.addtext1 = function () {
$scope.sig.sigBase6422 += "1111111111111111";
};
$scope.addtext2 = function () {
$scope.sig.sigBase6422 += "2222222222222222";
};
$scope.sig = {
sigBase6422: ""
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<form action="#" name="FORM1">
<TEXTAREA ng-model="sig.sigBase6422" ROWS="10" COLS="20">String: </TEXTAREA>
</form><br/>
<input type="text" name="myID1" id="myID1" ng-model="sig.sigBase6422" /><br/>
<input type="text" name="myID2" id="myID2" ng-model="sig.sigBase6422" /><br/>
<p>Value {{sig.sigBase6422}}!</p>
<!-- test field -->
<button ng-click="addtext1()">Add text 1</button>
<button ng-click="addtext2()">Add text 2</button>
</div>
You seem to have misunderstood how angular works. What you're trying to do is not how angular works. What you're trying to do with native JavaScript can be done with angular. Angular can update dom and Dom updates angular as it's responsible for causing updates.... anyway without getting any deeper. You need to read more on how angular works and try sticl within the bounds of angular instead of mixing.
That being said :
Tigger change on the Dom element after you have updated its value. Or better yet get access to scope variable on the Dom and call a function in angular with the value you're and set they value from inside of a angular.
Use this code while updating the value.
pick the controller first using
var scope = angular.element(document.getElementById('yourControllerElementID')).scope();
scope.<variablename> = <your operation>;
then
scope.$apply();
the remaining thing will be taken care by Angular.
A few days back, I asked the following question:
I've searched for how to do this, and I've not had any luck. I'm fairly inexperienced with web stuff, so perhaps it's so trivial that no one needs to ask how to do it :(
Suppose I have an HTML text input field with a label, like this:
<label for = "stuff">Stuff</label>
<input type = "text" name = "stuffz" id="stuff" value = "hello!">
Now suppose the text input field value is changed. Is there a way to use AngularJS to restyle the label (Like, turn it green, for example) when this change occurs? I've looked into using ng-change and ng-class, but I'm not knowledgeable enough about how these work to use them in this manner.
When I tested the solution provided, which was:
CSS
.marvellous {
color: green;
}
HTML
<div ng-app="demo">
<label for="stuff" ng-class="{ 'marvellous' : !!hasChanged }">Stuff</label>
<input type="text" id="stuff" ng-model="myModel" ng-change="hasChanged = true"></div>
It worked, but only when I manually changed the text field (i.e. I typed stuff in the text field directly). However, in the particular application I'm working on, I need for the labels to be restyled when the value stored in ng-model changes. Unfortunately, I falsely assumed that if this method worked when I manually changed the text field, it must work if ng-model were to change as well. I've come to find out that it doesn't.
What's the reason for this? And how can I make the label re-style when ng-model changes?
Thanks!
EDIT: When I say "ng-model changes," what I mean is..in my controller, there is a variable that is used to populate the text fields of the app that I'm working on. However, when the user clicks an "import changes" button, this variable is changed according to the changes that they are importing, which consequently changes the corresponding text fields linked to that variable. Ultimately, I want all of the labels attached to these changed text fields to be highlighted for the user to see. I'm sorry for my vagueness.
Each input in an angular js form has meta data properties to help you. For example
<form id="form">
<label for="stuff" ng-class="{ 'marvellous' : form.stuff.$dirty}">Stuff</label>
<input type="text" id="stuff" ng-model="myModel" ng-change="hasChanged = true">
</form>
https://docs.angularjs.org/api/ng/type/form.FormController
You can achieve that using $scope.$watch :
function demoCtrl ($scope) {
$scope.$watch('myModel', function (newValue, oldValue) {
if (newValue) {
$scope.hasChanged = true;
}
});
$scope.changeMyModel = function () {
$scope.myModel = 'wonderful';
};
}
.marvellous {
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="demoCtrl">
<label for="stuff" ng-class="{ 'marvellous' : !!hasChanged }">Stuff</label>
<input type="text" id="stuff" ng-model="myModel" ng-change="hasChanged = true">
<button ng-click="changeMyModel()">change model</button>
</div>
<!--Use ng-style !!! replace your lable with this--->
<label for="stuff" ng-style="hasChanged()">Stuff</label>
and define your function like this below---
$scope.hasChanged = function(){
if($scope.myModel !== initValue){
return { color: "green" }
}
}
Whenever any non-readonly input in my form changes and the form is valid, I want to do certain action. Let's say, my form looks like
<form name="form" novalidate>
<input ng-model='input.a' required/>
<input ng-model='input.b' required/>
<input value='{{output.p | number: 2}}' readonly/>
<input value='{{output.q | number: 2}}' readonly/>
</form>
Now upon any change of input, I want to do something, whenever input.a and input.b are valid. I tried $watch(input), but it didn't work. Watching all its members does, but it feels stupid. Adding ng-change to all fields feels better, but still pretty stupid (non-DRY). What's the proper way?
The other question is how to find out if the input is valid. If I had a button, I could do simply
<button ng-click="doIt()" ng-disabled="form.$invalid">
but how can I access form.$invalid in the controller (it's not contained in $scope)?
You should be able to access form.$invalid by doing
$scope.form.$invalid
See here: AngularJs can't access form object in controller ($scope)
To watch for changes in the form, you should be able to do:
$scope.$watchCollection('input')
#dave has already answered your first question, but for the second I have a solution that I consider more elegant:
In your controller you have declare an object, for example:
$scope.forms = {};
Then you form name must be nested inside that object:
<form name="forms.someForm">
...
Finally in your controller you can do things like this:
if($scope.forms.someForm.$invalid) {
...
}
I have a problem where I'm attempting to post the value of a checkbox in my model to the server and as the checkbox has not been interacted with on the form, angular seems to have not assigned it a value, when I ask for the value of the checkbox it comes back as undefined.
Here is my markup:
<div class="form-group">
<input id="templateDisable" type="checkbox" ng-model="template.disabled" />
<label for="templateDisable">Disabled</label>
</div>
And here's a reduced version of my save action on my controller:
$scope.save = function (form) {
if (form.$valid) {
var formData = new FormData();
// this is the problem line of code
formData.append("disabled", $scope.template.disabled);
// ... some other stuff
}
};
Actually, ticking then unticking the checkbox before I hit the save action results in the template.disabled property being false, which is what I would have expected without any manual intervention.
I've seen other related questions, e.g. AngularJS: Initial checkbox value not in model but surely stuff like a simple checkbox should be baked in? I shouldn't have to be writing directives to manage checkboxes surely?
This is per design. If you want a default value on your model than you should initialise it inside the controller (recommended), or make use of ng-init.
app.controller('AppController',
[
'$scope',
function($scope) {
$scope.template = {
disabled = false
};
}
]
);
<div class="form-group">
<input type="checkbox" ng-model="template.disabled" ng-init="template.disabled=false" />
<label>Disabled</label>
</div>
The following will always set the state back to "unchecked" when the page is loaded (or refreshed). In other words it will overwrite the user's actual selection whenever the page is refreshed.
<input type="checkbox" ng-model="template.disabled"
ng-init="template.disabled=false" />
If, however, you want the checkbox state set to a default state initially and you also want it to remember user interactions, then the following is what you want.
<input type="checkbox" ng-model="template.disabled"
ng-init="template.disabled = template.disabled || false" />
In AngularJS I have input that is populated by php like so:
<form method="post" ng-controller="PostCtrl">
<input type="text" name="post_title" ng-model="post_title" />
</form>
Now in my Controller, I never to specify ng-model, so I lets imagine I have empty controller:
EngagementApp.controller('PostCtrl', ['$scope',
function($scope) {
return function($scope) {
}
}]);
The problem I am having is that anything tied to an ng-model automaticcaly gets replaced with an empty value. My question is how can I stop the default php value from being replaced if no value in the controller is set?
You can use ng-init to set an inital value. For example
<input type="text" name="post_title"
ng-model="post_title" ng-init="post_title='<?$=phpValue;?>'" />
The HTML value attribute is ignored by AngularJS.
You should could the default values from your controller:
$scope.post_title = 'default value';
But initializing the model from the html by using ng-init ( like #Thomas suggested ) makes more sense in this particular case.