Weird Angular ng-model issue - javascript

I have a weird question regarding my Angular app.
I wanted to get the input texts when user enter texts in the input box.
my html
<input type="text" class="form-control" ng-model="texts" ng-change="type()"/>
my js
$scope.type = function() {
console.log($scope.texts)
console.log($scope) //doesn't see texts property either
}
However, every time I type something, the first console log shows 'undefined'. It's like controller can't find the texts property. Can anyone help me this weird issue? Thanks a lot!

This can be accomplished by using angular's two-way data binding system:
Data-binding in Angular apps is the automatic synchronization of data
between the model and view components. The way that Angular implements
data-binding lets you treat the model as the single-source-of-truth in
your application. The view is a projection of the model at all times.
When the model changes, the view reflects the change, and vice versa.
This allows us to synchronize the properties of our controller's scope by binding to them in our html.
So, we might define our controller like this:
myApp.controller('SomeController', function ($scope) {
$scope.text = "";
});
Now, we can use this in our html like this:
<div ng-controller="SomeController">
<input type="text" class="form-control" ng-model="text" />
</div>
The important thing to notice here is the ng-model directive. Here we bind the text property we defined in our controller to the <input> field. Now, with two-way binding, if we type into the input field it will automatically update the text property. This way we can access the value of the input field within our controller without having to do any extra work.
Here is a plnkr with a working example: http://plnkr.co/edit/xEkoDbPxwrWgGfuEiS3a?p=preview
Hope this helps :-)

$scope has to be passed in to the controller. Check your controller arguments.

Related

Angular template variable reference

Here is a weird problem in Angular:
<input #pin1 type="password">
<p>You entered: {{pin1.value}}</p>
If you type something in <input>, the <p>'s content will not change which means pin1.value does not have value, does it mean the variable reference #pin1 does not work?
On the other hand, if we add a function to pass the reference, it will work.
<input #pin2 type="password" (input)="test(pin2)">
<p>You entered: {{pin2.value}}</p>
where test=function(x){console.log(x);}
For this <input>, if we type something, the the <p>'s content will change to corresponding text which implies #pin2 works.
So, the question is, in Angular, why we must use function to pass variable reference firstly then we can use it, why we cannot directly use variable reference.
Firstly, that is not how binding works.
What you did is creating a reference to input Dom object. At the time of the creation, the value of that Dom element (input) was empty. hence no value showing in your <p> tag.
if you want to see the value as you type then you are looking for a 2 way binding like so
<input [(ngModel)]="pin" type="password">
<p>You entered: {{pin}}</p>
Assuming that pin is declared in your ts file.
As to why the value was updating when you introduces a function, the answer is because Angular will be calling that function test(pin2) whenever you type something into that input which results in running a detect change on the model.
Long story short, Angular is a Model driven framework, if you need a value, you shouldn't need to get the DOM element to get the value from there.
I may get an ambiguous answer, it may be related to event binding, which means "view-to-source", if we didn't bind any event, the view (user interaction) cannot pass data to source (the component class), so variable reference may not work, but there are still some question like the template references should not be related to source side, since such variables aren't member/properties of component class.
it is so werired behaviour in angular
this code not working
<input #inputval type="text" />
<app-newcomp [testValue]="inputva.value"></app-newcomp>
but if you add "input" event to the input element then it will work
<input #inputval type="text" (input)="someFunctionInTs($event)" />
<app-newcomp [testValue]="inputva.value"></app-newcomp>

Updating one input by changing another input in angularJS but directly inside html

I have two input with different model, one of these input may change and be updated. I want the other input to have the save value as the first one. I do not want to use $watch. I am using ng-change for the first
this is the first input:
<input type="text" placeholder="input one" class="form-control" ng-change='second_model=data.first_model' ng-model="data.first_model" required>
And this is the second input:
<input type="text" placeholder="input two" class="form-control" ng-model="second_model" disabled required>
The ng-change is not working unless the input value of first input changes by typing inside the first input field. When the data.first_modelis updated inside the controller the ng-change is not doing its job.
I know a solution to force the second one to get the value from the first is using $watch like this:
$scope.$watch('data.first_model', function(v){
$scope.second_model =v;
});
But I have a constrain that I can't call function inside controllers I want to handle it right inside the html code as you see I did like this:
ng-change='second_model=data.first_model'
But ng-change do not do its job if the first one change by some function inside the controller. I highly appreciate any trick or solution.
See this code it helps you. I think ng-change is not required for your scenario.
HTML:
<input type="text" placeholder="input one" class="form-control" ng-model="data.first_model" required>
<input type="text" placeholder="input two" class="form-control" ng-model="data.first_model" disabled required>
app.js (controller):
app.controller('MainCtrl', function($scope) {
$scope.data={};
$scope.data.first_model="Kumar";
});
to view see this plunker link: https://plnkr.co/edit/H0yFffJG3EqpDipbqhX7?p=preview
I m not sure if I understand your question properly, if you just want to have a duplicated display, you can just bind to the same model.
However, if you want to have A affect B without function while B can still have its own variable without reflecting back to A, wrap the element that B is binded in a directive and passing A to the directive, and inside of directive define the parameter scope as read only and assign it to B, so A will change B while B can still make change without hurting A.
From your question:
The ng-change is not working unless the input value of first input changes by typing inside the first input field. When the data.first_modelis updated inside the controller the ngChange is not doing its job.
This is the problem. ng-change is doing it's job.
From the docs:
ngChange: Evaluate the given expression when the user changes the input.
ngChange is only fired when the user changes the input in the view. ngChnage will not fire if the model is changed outside the view, such as in the controller, regardless of if the model is bound to the input.
If you are changing the value of your first model outside of the view, then your only option is to update the value of the second model also outside of the view.
You'll need to change the architecture of how you are trying to accomplish what you are trying to accomplish. If you post your full code, we can be of more help.

Angular js : ng-model default value of input is not set in model

I am using ng-model to link input values with model.
If I set default value in input box it does not show in $scope, but If I change anything in this input I can see changes.
<input type='text' id="save_quote_email" name="save_quote_email" ng-model="AutoQuote.postAutoQuoteObj.ApplicationInfo.GeneralPartyInfo.ContactInfo.Emails[0].EmailAddress" value="praveend06#gmail.com" />
{{AutoQuote.postAutoQuoteObj.ApplicationInfo.GeneralPartyInfo.ContactInfo.Emails[0].EmailAddress}}
I can set this value in controller, then it will work, but such values will come in form when my html loaded.
First, you shouldn't use ng-init in this case.
From docs:
This directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit, such as for aliasing special properties of ngRepeat, as seen in the demo below; and for injecting data via server side scripting. Besides these few cases, you should use controllers rather than ngInit to initialize values on a scope.
Then, simply do it in your controller:
AutoQuote.postAutoQuoteObj.ApplicationInfo.GeneralPartyInfo.ContactInfo.Emails[0].EmailAddress = "praveend06#gmail.com";
Add
ng-init="AutoQuote.postAutoQuoteObj.ApplicationInfo.GeneralPartyInfo.ContactInfo.Emails[0].EmailAddress='praveend06#gmail.com'"
ng-init="AutoQuote.postAutoQuoteObj.ApplicationInfo.GeneralPartyInfo.ContactInfo.Emails[0].EmailAddress='praveend06#gmail.com'"

Change placeholder of input from angularjs directive wake scope model 'undefined'

So I have some trouble with my angularjs application. I try to implement a specific directive that make allow to translate my app easily. It works well on my text fields, but it doesn't work on input field to change my placeholder.
To be clear, here you can see some code sample :
http://plnkr.co/edit/GUS2FYCxA6wAOtkoxG66
$scope.validform = function() {
console.log($scope.valuefield);
};
As you can see, when i click on the button, my input model "valuefield" is "undefined". Or i want to see the value of the input.
What seems really strange for me is that the directive change the placeholder, but do not touch at the model.
I think I have to be more specific on the scope definition of the directive, or to use some $watch function but I am not sure how.
Can anyone guide me on this?
Ok, so finally it was pretty easy.
I only had to change my directive parameter from
scope : true
to
scope : false
By doing this, my directive is using the exact same scope than the controller. So The scope controller is not change and steal working as it should be.

Splitting HTML components for one controller causes controller to stop working

If I create two div's, both controlled by the same controller, Angular's controller seems to stop updating my view.
I've put together a bare-bones example to demonstrate this. It is easiest to view the sample here on JSFiddle, but I'm also posting the code below.
HTML
<div ng-app='App'>
<div ng-controller="MyCtrl">
<form>
<input type="text" ng-model="search.query"></input>
<button ng-click="search.submit()">Submit</button>
</form>
</div>
<div ng-controller="SomeOtherCtrl">
{{sampleText}}
</div>
<div ng-controller="MyCtrl">
<button ng-click="search.reset()">Reset Form</button>
</div>
</div>
JS
var app = angular.module('App',[]);
function MyCtrl($scope)
{
$scope.search = {
query : 'foobar',
submit : function() {
this.query = 'Submitted';
console.log(this.query);
},
reset : function() {
console.log('resetting');
this.query = '';
}
};
}
function SomeOtherCtrl($scope) {
$scope.sampleText = 'other controller text';
}
The submit button works fine, but when I click on the Reset button, I see resetting get logged in the console, but my view (the form input) does not update.
Why is this so? In a current project I'm working on, I'm forced to do this because certain HTML that falls in between belongs to another controller. How can I work around this?
A controller definition in angular is actually a Class / Constructor and not an Object. Each place in the HTML that controller is referenced, during the compilation phase, angular creates a new controller object using the defined controller class. So, you could refer to more than one scope with the same controller class.
You might have already heard of services in Angular and this is exactly a place where you need to use them to solve it. search that you are using is a common object that is being shared by two controller instances ( Note the class is the same MyCtrl but by putting in two ng-controller="MyCtrl" you asked Angular to create two instances of MyCtrl ). So these two objects have access to two different scopes and when they are created the two different scopes are set with two different search objects. When you click on reset, the other search objects reset gets called, which means nothing happens in the first MyCtrl's scope. This is the reason why your code doesnt work as expected.
Now note that in angular services are singletons. So if you reference them in multiple places you get access to the same object. So, resetting in a different controller (instance) will still reset the same object.
Here is a plunk that works with your code.
http://plnkr.co/edit/zynAdS9hg8DUZDnlnYFm?p=preview
I have no idea how angularjs works but if you put 2nd input <input type="text" ng-model="search.query"></input> near to reset button, this input will be updated.
Should inputs be inside the same div controller?
Will it help you to solve your problem?
Looking at your sample it seems that you are missing form tag for reset button. From angular perspective if you can use one outer div for controller="MyCtrl" where you have a form with two buttons-submit() and reset() and inside the outer div you put your nested controller "SomeOtherCtrl" then it should work perfectly.

Categories