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.
Related
I'm currently confuse in trying to obtain the value inside a text box using jquery .value
<input class="input referral-code" disabled="true" ng-model="account.referral_code_string" id="input-refcode">
I tried using document.getElementById('input-refcode').value to try to obtain the value but it comes out as empty on my console.
But if I tried binding it onto a on-click event, it manages to obtain the value stored inside the ng-model
$('.trigger').on('click', function(){
console.log(document.getElementbyId('input-refcode'))
});
As you can see there is a value inside the text box itself. But when you tried inspecting it, this is what came out.
<input class="input referral-code" disabled="true" ng-model="account.referral_code_string" id="input-refcode">
If you look at there is no value inside the input textbox. I'm not sure if it has something to do with angular.js
You can get the scope object using element
var scope = angular.element(document.getElementById('input-refcode')).scope();
var desiredValue = scope.account.referral_code_string;
This might help you.
inject $timeout service in controller
$timeout(function(){
console.log(document.getElementById('input-refcode')); },200);
Note: Use capital B in getElementById not getElementbyId.
var app = angular.module('todoApp', []);
app.controller('TodoListController', function($scope){
$scope.$watch('referral_code_string'), function(){ console.log($scope.referral_code_string)};
console.log(document.getElementById('input-refcode').value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="todoApp" ng-controller="TodoListController as todoList">
<input class="input referral-code" disabled="true" ng-model="referral_code_string" ng-init="referral_code_string = 'abc'" id="input-refcode" value="abc">
</div>
JSFiddle here: http://jsfiddle.net/c6tzj6Lf/4/
I am dynamically creating forms and buttons and want to disable the buttons if the required form inputs are not completed.
HTML:
<div ng-app="choicesApp">
<ng-form name="choicesForm" ng-controller="ChoicesCtrl">
<div ng-bind-html="trustCustom()"></div>
<button ng-repeat="button in buttons" ng-disabled="choicesForm.$invalid">
{{button.text}}
</button>
</ng-form>
</div>
JavaScript:
angular.module('choicesApp', ['ngSanitize'])
.controller('ChoicesCtrl', ['$scope', '$sce', function($scope, $sce) {
$scope.custom = "Required Input: <input required type='text'>";
$scope.trustCustom = function() {
return $sce.trustAsHtml($scope.custom);
};
$scope.buttons = [
{text:'Submit 1'},
{text:'Submit 2'}];
}]);
choicesForm.$invalid is false and does not change when entering text into the input field.
Solution:
I ended up using the angular-bind-html-compile directive from here: https://github.com/incuna/angular-bind-html-compile
Here is the relevant bit of working code:
<ng-form name="choicesForm">
<div ng-if="choices" bind-html-compile="choices"></div>
<button ng-click="submitForm()" ng-disabled="choicesForm.$invalid">
Submit
</button>
</ng-form>
And choices might be a snippit of HTML like this:
<div><strong>What is your sex?</strong></div>
<div>
<input type="radio" name="gender" ng-model="gender" value="female" required>
<label for="female"> Female</label><br>
<input type="radio" name="gender" ng-model="gender" value="male" required>
<label for="male"> Male</label>
</div>
The main problem is that ngBindHtml doesn't compile the html - it inserts the html as it is. You can even inspect the dynamic input and see that it doesn't have the ngModel's CSS classes (ng-pristine, ng-untouched, etc) which is a major red flag.
In your case, the form simply doesn't know that you've added another input or anything has changed for that matter. Its state ($pristine, $valid, etc) isn't determined by its HTML but by the registered NgModelControllers. These controllers are added automatically when an ngModel is linked.
For example this <input required type='text'> won't affect the form's validity, even if it's required, since it doesn't have ngModel assigned to it.
But this <div ng-model="myDiv" required></div> will affect it since it's required and has ngModel assigned to it.
The ngDisabled directive on your buttons works as expected since it depends on the form's $invalid property.
See this fiddle which showcases how ngModel registers its controller. Note that the html containing the dynamic input gets compiled after 750ms just to show how NgModelControllers can be added after FormController has been instantiated.
There are a few solutions in your case:
use a custom directive to bind and compile html - like this one
use ngInclude which does compile the html
use $compile to compile the newly added HTML but this is a bit tricky as you won't know exactly when to perform this action
This is an answer yet imcomplete because i cannot do the code at the moment.
I think your html will be included, not compiled. So the inputs are not bind to angular and are not part of the angular form object.
The only way i see is to use a directive that will compile the passed html and add it to your form. This may be quite tricky though, if you want to go on this way i suggest to edit your question to ask for the said directive.
However i'm not really familiar with $compile so i don't know if it'll work to just add $compile around $sce.trustAsHtml()
You can write a method as ng-disabled does not work with booleans, it works with 'checked' string instead:
So on your controller place a method :
$scope.buttonDisabled = function(invalid){
return invalid ? "checked" : "";
};
And on your view use it on angular expression :
<button ng-repeat="button in buttons" ng-disabled="buttonDisabled(choicesForm.$invalid)">
Here is a working fiddle
Working DEMO
This is the solution you are looking for. You need a custom directive. In my example I have used a directive named compile-template and incorporated it in div element.
<div ng-bind-html="trustCustom()" compile-template></div>
Directive Code:
.directive('compileTemplate', function($compile, $parse){
return {
link: function(scope, element, attr){
var parsed = $parse(attr.ngBindHtml);
function getStringValue() { return (parsed(scope) || '').toString(); }
//Recompile if the template changes
scope.$watch(getStringValue, function() {
$compile(element, null, -9999)(scope); //The -9999 makes it skip directives so that we do not recompile ourselves
});
}
}
});
I found the directive in this fiddle.
I believe what is really happening though due to jsfiddle I'm unable to dissect the actual scopes being created here.
<div ng-app="choicesApp">
<ng-form name="choicesForm" ng-controller="ChoicesCtrl">
<div ng-bind-html="trustCustom()"></div>
<button ng-repeat="button in buttons" ng-disabled="choicesForm.$invalid">
{{button.text}}
</button>
</ng-form>
</div>
The first div is your top level scope, your form is the first child scope. Adding the div using a function creates the dynamically added input field as a child of the first child, a grandchild of the top level scope. Therefore your form is not aware of the elements you're adding dynamically causing only the static field to be required for valid form entry.
A better solution would be to use ng-inclue for additional form fields or if your form isn't to large then simply put them on the page or template you're using.
I got this example from the W3Schools tutorial on AngularJS. I made a small change from binding the value of the checkbox span to using an expression. I figured that the todo list wouldn't update any more. But it still does. What causes the ng-repeat to fire just because I have added a todo item?
http://plnkr.co/edit/Kojz2ODWDS8dFDNzjYR5?p=preview
<!DOCTYPE html>
<html>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body ng-app="myApp" ng-controller="todoCtrl">
<h2>My Todo List</h2>
<form ng-submit="todoAdd()">
<input type="text" ng-model="todoInput" size="50" placeholder="Add New">
<input type="submit" value="Add New">
</form>
<br>
<div ng-repeat="x in todoList">
<input type="checkbox" ng-model="x.done"> <span>{{x.todoText}}</span>
</div>
<p><button ng-click="remove()">Remove marked</button></p>
<script>
var app = angular.module('myApp', []);
app.controller('todoCtrl', function($scope) {
$scope.todoList = [{todoText:'Clean House', done:false}];
$scope.todoAdd = function() {
$scope.todoList.push({todoText:$scope.todoInput, done:false});
$scope.todoInput = "";
};
$scope.remove = function() {
var oldList = $scope.todoList;
$scope.todoList = [];
angular.forEach(oldList, function(x) {
if (!x.done) $scope.todoList.push(x);
});
};
});
</script>
</body>
</html>
Clicking the Add New Button submits the corresponding form and by using ng-submit="todoAdd()" it will call this function. This in turn adds an entry to the todoList in your scope. As this array has been modified the angular digest cycle is triggered and the list is updated.
Some suggestions for your questions: First of all, you mean W3Schools, not the W3C (which is a standardization organization and normally is not doing tutorials, which is why I got curios - Also, you will find lots of reasons why not to use W3Schools when goolgin around or looking at meta). Also, if you compare to some other code, you should include it or at least link to it.
I found it by googling and it seems your only change is using <span>{{x.todoText}}</span> instead of <span ng-bind="x.todoText"></span>. There really is no difference in terms of the digest cycle here. The only difference is that by using {{}} it might at first be rendered as curly brackets in the browser window, before the variable is actually replaced. Thus, it is usually better to use ng-bind.
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.
I am trying to change input value in particular web site from chrome extension. In order to do that I am using jQuery in my content script. It works in most of the cases, but I didn't manage to change value of the input when it is part of AngularJS view. I found the same problem when I use let say kendoUI. I am trying to set the value calling $('element').val('value') and then try to call blur and change event, but without any success.
I went through may be 99% of the posts related to this topic, but still can't find working solution.
You just need to Call $scope.apply() in order to let angular know about updating the bindings. This is mainly because by default, angular doesn't know anything about the changes you are making in jQuery.
Below is a sample code, and here is a jsFiddle. Hope this helps.
app.controller('testCtrl', ['$scope', function ($scope) {
$scope.changeValue = function() {
$('#test').val("new Value");
$scope.apply();
}
<div class="form-inline">
<input type="text" id="test" value="test">
<input type="submit" value="submit" ng-click="changeValue()">
</div>