I have a modal whose contents is generated by an JavaScript method (the reason being that the contents strongly depends on data retrieved from the DB, including hierarchy and its structure).
Initially, I had checkboxes deployed (as part of the generated HTML) as follows:
<input type="checkbox"
id="Chkbox_1"
onClick="Handle_Select(this,1,'Topic_34343')">
and, within the javascript (in Handle_Select) I could verify if the checkbox was checked or not by testing this.checked as follows:
Handle_Select = function (p_this,p_Topic_ID, p_Topic_Name) {
if(p_this.checked) {...}
}
Now, I replaced the onClick by ng-click (as stated, I'm using AngularJS) and suddenly this no longer holds the properties of the input element but what appears to be the contents of the controller. Of course, the same function now looks:
$scope.Handle_Select = function (p_this,p_Topic_ID, p_Topic_Name) {...}
It is better to use this syntax:
<input type="checkbox"
id="Chkbox_1"
ng-click="Handle_Select($event, 1, 'Topic_34343')">
Angular code will be:
$scope.Handle_Select = function ($event,p_Topic_ID, p_Topic_Name) {
var target = $event.target;
if (target.checked) {
// some code
}
}
Angular comes with some handy directives that abstract a lot of the typical javascript boilerplate code. In this case, consider using the ng-model and ng-checked directives. ngModel will bind your input element to a value defined on your scope, and ngChecked will check or uncheck the input depending on a property you define:
<input type="checkbox"
id="Chkbox_1"
ng-model="your_scope_data" ng-checked="your_scope_data.is_checked">
so define $scope.your_scope_data in your controller, and then angular will tie it together with your template so that the values stay in sync. your_scope_data.is_checked is an arbitrary property of the data you bound with ng-model to the input element. You can also evaluate a simple expression in ng-checked if you want to perform comparisons, etc. Hope this helps, and good luck!
Related
I want to access form input value in services.
var emailId = document.getElementById("save_quote_email").value;
console.log("emailId="+emailId);
console.log("emailId2="+angular.element('#save_quote_email').val());
I am able to get value using document.getElementById("save_quote_email").value but not using angular function angular.element('#save_quote_email').val()
It gives error
Error: [jqLite:nosel] Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element
http://errors.angularjs.org/1.2.16/jqLite/nosel
Please view this plunker http://plnkr.co/edit/Op1QDwUBECAosPUC7r3N?p=preview for complete code.
in dtoresource.js line numbe2 21.
You can't use angular.element to select by id or some other selector Link provide by you give full info as below
"Note: Keep in mind that this function will not find elements by tag name / CSS selector. For lookups by tag name, try instead angular.element(document).find(...) or $document.find(), or use the standard DOM APIs, e.g. document.querySelectorAll()"
you may use document.query selector as follow
var queryResult = document.querySelector('#save_quote_email');
var emailId2 = angular.element(queryResult);
Here is working plunker http://plnkr.co/edit/mC0JKTZpdnvqyBpihLRW?p=preview
Also this https://stackoverflow.com/a/23626251/5621827 will help you to understand it batter
Instead of trying to answer your question I am going to rather direct you to the correct way of using Angular.
You should never try and select input values, that is what ng-model is for.
ng-model bind the input to a value. As soon as the value changes Angular automatically updates the scope value, no functions of getting data necessary.
I can't make heads or tails out of your plunkr code but you should not do this:
var queryResult = document.querySelector('#save_quote_email');
Also you are trying to access the DOM from a factory, you should rather pass the needed value to an exposed function of the factory and call the function in your controller.
In your controller autoQuoteCtrl you should use a simply scope value for your input like so:
$scope.email = "";
And in your index the input should read:
<input type='text' ng-model="email" />
{{ email }}
Do not use convoluted variables like AutoQuote.postAutoQuoteObj.ApplicationInfo.GeneralPartyInfo.ContactInfo.Emails[0].EmailAddress in your scopes, you should assign the values when they are received from the resource.
$http({url: url}).then(function (rs) {
$scope.email = rs.postAutoQuoteObj.ApplicationInfo.GeneralPartyInfo.ContactInfo.Emails[0].EmailAddress;
}
I can't understand why angular ng-change function are called only in first click. In this example
http://jsfiddle.net/ZPcSe/5/
function is called every time when i change current radio selection, but in my code something is wrong
http://jsfiddle.net/4jL3u8ko/1/
Can someone change my code to work like first example, and explain why it isn't working?
Great question.
This is not an answer but one may call this explanations to answers and any further problems that may occur. And this happens quite often, so its important to understand. The answer given by #Victor is ok and the comment of #Atias is also helpful.
Explanation -
Simple explanation : ng-repeat forms child scope.
Little detailed :
So your application has 3 scopes (or may increase depending on the number of values in $scope.radioButtons). Let me name them - parentScope(main scope), childScope1(scope of first element of ng-repeat) and childScope2(scope of second element of ng-repeat).
Parent scope variables : calledFunctions(array), radioButtons(object) and newValue(function)
ChildScope1 variables : name(assigned a literal at the start), val(assigned an object at start) and value(it has no value, or undefined)
ChildScope2 variables : name(assigned a literal at the start), val(assigned an object at start) and value(it has no value, or undefined)
What happens when you click on the radio button of childScope1(for first time):
ChildScope1.value = ChildScope1.name or ChildScope1.value= "Radio1"; the ng-change directive checks if this scope's model has been changed? Yes, as it was undefined and now it has a literal("Radio1")!! So call ChildScope1.newValue(), which obviously is not present. Therefore now look for parent- call parentScope.newValue(). This is present, so execute it.
keep in mind that ChildScope1.value= "Radio1";
After clicking on other radio buttons......
Now lets click 2nd time on ChildScope1's radio button. After clicking it- ChildScope1.value = ChildScope1.name or ChildScope1.value= "Radio1"; the ng-change directive checks if this scope's model has been changed??? No!! Because it still contains the same literal vaule as before, so do not even look for ChildScope1.newValue() or ParentScope.newValue() function.
Now same thing happens with ChildScope2.
Hope this explains why your fiddle works like a one time binding, or how #Victor or #Atias are correct.
Simply the solution is - The ng-model of ChildScope1 or ChildScope2 or any other child scopes, should point to a variable of parent scope. So you can use $parent or make an object in parent scope(main scope) with a property( eg.- ParentVal={ChildVal = ""};). And in ng-model inside ng-repeat- write ng-model=ParentVal.ChildVal.
Sorry for my poor english and please pardon my spelling mistakes if there is any.
Thanks
ng-model is tricky. You should always, always have a dot in your models, or you get this kind of problem where you are creating several models and you think you only have one.
As a quick fix, use $parent.value instead of just value in your ng-model and ng-change.
As a good fix, have a proper model object in the scope, instead of storing values directly in the scope:
$scope.model = {};
ng-model="model.radiosValue"
As an even better fix, use the controllerAs pattern and use that object as the view model.
I know two ways to bind HTML to client-side JavaScript code and stay a kind of object-oriented:
Use a lot of IDs (or special CSS class names, or some other distinct HTML attributes) in HTML and do a "harvest" in JS initialization method (or request each DOM object each time, right before use);
Do not write HTML at all. Construct an element at runtime, in initializer, and remember a reference to DOM object (or jQuery object) in a variable.
Are there some other ways that allow to use design-time phase (writhing HTML) which is much more convenient than doing all the work at runtime, and at the same time do not use a lot of identifiers of any kind having to maintain their uniqueness?
AngularJS is the framework you want to use for 2-way data binding.
I used AngularJS for multiple projects now, combined with nodeJS, and I never looked back at jQuery, you keep your code clean with the MVC pattern and manipulating the DOM is made easy and clear.
Example for 2 way data binding:
HTML
<p>{{elementText}}</p>
<input type="text" ng-model="item.value" />
JavaScript/Controller
$scope.item = {
value: ''
};
$scope.elementText = "The text you want to display";
console.log($scope.item.value); //Directly get your values from the scope.
Want to assign values to <select> boxes or fill <table>'s using JSON data? No problem, AngularJS got you covered.
Interesting AngularJS features:
ng-model
ng-repeat
Animations
Custom directives
I hope this will help you!
In this tutorial by Jenkov, he asserts that you can give a form a name, and then access it in the controller by
$scope.FORM_NAME.INPUT_NAME
For example like
<form name="myFormNg" ng-submit="myForm.submitTheForm()" >
<input name="firstName" type="text" ng-model="myForm.firstName">
</form>
and then in Angular
$scope.myFormNg.firstName
However, when I try it, instead of getting what I typed into the input box (abc), I get this whole object:
{"$viewValue":"abc","$modelValue":"abc","$$rawModelValue":"abc","$validators":{},"$asyncValidators":{},"$parsers":[],"$formatters":[null],"$viewChangeListeners":[],"$untouched":false,"$touched":true,"$pristine":false,"$dirty":true,"$valid":true,"$invalid":false,"$error":{},"$$success":{"parse":true,"required":true},"$name":"email","$options":null,"$$lastCommittedViewValue":"abc"}
Why? Is there a cleaner way to do it that Jenkov omits?
Actually, Jenkov mentions (and quite clearly) one thing: with $scope.formName.inputName you'll get an instance of ngModelController (and only if this input is already bound - with ng-model or in some other way).
This instance has many uses; you can get back its view value (via $viewValue property; see this demo), check whether or not it passes validation etc. - but it's still an Object, not a string.
I've seen this function used in several examples for form validation but can't find any info/docs/api for it and seems not to work in all cases. Is there an alternative for checking has the object changed ?
I have seen the method in AngularJS tutorials, and its just a custom function
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
The above check i believe is reference match not the complete content.
You can use $watch method to watch any change on object. Also go through FormController it has properties like $pristine, $isDirty etc which is specific to form editing. I believe these values are also available on form elements.