I want to submit text stored in a ng-model via JavaScript. I have the following code:
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
<body>
<div ng-app>
<div ng-controller="Ctrl">
<form ng-submit="submit()">Enter text here:
<input type="text" ng-model="in" name="text" />
<input type="submit" id="submit" value="Submit" /> <pre>Last input: {{active}}</pre>
</form>
</div>
</div>
<script>
function Ctrl($scope, $http) {
$scope.active = "none";
$scope.in = "enter input here";
$scope.submit = function () {
$http.post("do_something.php",{sometext:$scope.in})
.then(function(response) {
$scope.active = response.data;
});
};
}
</script>
</body>
</html>
I want to write an extension, that enters text into the input field and submits it.
I use JavaScript to access the elements which have the ng-model, and change their value:
document.getElementsByTagName("input")[0].value="hello";
this only changes the text in my input field, but does not affect the actual in-variable. when submitting the form via
document.getElementsByTagName("input")[1].click()
The submitted input is not the input it previously changed to, but instead the old input - not visible any more.
I think this is because changing values via Javascript does not change the ng-model according to the input fields value.
How can I do this properly?
This is not very good idea to modify Angular models from outside of the Angular app itself. But given that you have a good reason for that you can do it like this:
var input = angular.element(document.getElementsByTagName("input")[0]);
var model = input.controller('ngModel');
model.$setViewValue('New value');
model.$render();
input.parent('form').triggerHandler('submit');
By working with ngModelController directly you have a benefit that you don't have to know the actual model name. You just use ngModelController API. Another benefit is that you don't need to do error prone stuff like document.getElementsByTagName("input")[1].click(). Instead, just directly trigger function used by ngSubmit directive.
Here is a quick demo:
function Ctrl($scope) {
$scope.in = "enter input here";
$scope.submit = function() {
alert('Value submitted: ' + $scope.in);
};
}
function updateModel() {
var input = angular.element(document.getElementsByTagName("input")[0]);
var model = input.controller('ngModel');
model.$setViewValue('New value');
model.$render();
input.parent('form').triggerHandler('submit');
}
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
<div ng-app ng-controller="Ctrl">
<form ng-submit="submit()">
Enter text here:
<input type="text" ng-model="in" name="text" />
<input type="submit" id="submit" value="Submit" />
</form>
</div>
<hr>
<p>Set model from outside of the Angular app.</p>
<button onclick="updateModel()">Set model</button>
You are going out from the angular environment... That should be avoided, but, sometimes it's needed: in that case you need to manually trigger the $digest cycle, this is an example:
function onNoNgClick() {
var $scope = angular.element(document.getElementById('TestForm')).scope();
$scope.$apply(function() {
$scope.value = 'FOOBAZ';
return $scope.submitRequest();
});
}
function TestCtrl($scope) {
$scope.value = 'Initial Value';
$scope.submitRequest = function() {
console.log('sendData', $scope.value);
};
}
angular
.module('test', [])
.controller('TestCtrl', TestCtrl);
document.addEventListener('DOMContentLoaded', function() {
return document.getElementById('NoNG').addEventListener('click', onNoNgClick);
});
.no-ng {
padding: 1em;
border: 1px solid green;
margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section ng-app='test'>
<div ng-controller="TestCtrl">
<form ng-submit="submitRequest()" name="testRequest" id="TestForm">
<input type="text" ng-model="value" />
<button type="submit">Submit</button>
</form>
</div>
</section>
<div class="no-ng"><button id="NoNG">SetText: FOOBAZ</button></div>
Related
I'm trying to submit a form when user clicks on any part of the form, and then process it using AnglujarJS. Here's how I tried doing it:
<form ng-click="submit()" ng-app="MyApp" ng-controller="MyCtr">
<input type="text" ng-model="my_val" name="my_val" value="0" style="display: none"/>
</form>
var app = angular.module('MyApp', []);
app.controller('MyCtr', function($scope) {
$scope.submit = function() {
$scope.my_val; // This is undefined
});
};
});
The problem is that $scope does not have form values. If I replace ng-click with ng-submit, the values are present, but I don't want to submit form by clicking on a submit button.
You need to declare and set to 0 $scope.my_valoutside of submit function and also ij Js code there are unnecessary closed brackets check that as well.
var app = angular.module('MyApp', []);
app.controller('MyCtr', function($scope) {
$scope.my_val="0";
$scope.submit = function() {
$scope.fromvalue.my_val
console.log($scope.fromvalue.my_val.$viewValue);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form name="fromvalue" ng-click="submit()" ng-app="MyApp" ng-controller="MyCtr">
<input type="text" ng-model="my_val" name="my_val" value="0"/>
</form>
I am trying to get the value of the ng-model when clicking a button which triggers a function to add each ng-model value to an object. When trying to get the value of $scope.shipNameFirst, it comes up as undefined in the second example.
I've read that it's better to get the value of $scope on the view rather than passing it through the stripeBtn function, so ideally I'd like to do it that way. Hopefully this makes sense.
Can someone explain why this is not working?
Working
HTML
<input type="text" ng-model="shipNameFirst">
<input type="text" ng-model="shipNameLast">
<button type="button" ng-click="stripeBtn(shipNameFirst, shipNameLast)">Checkout with Stripe</button>
Controller
$scope.stripeBtn = function(shipNameFirst, shipNameLast){
$scope.details = {
recNameFirst: shipNameFirst,
recNameLast: shipNameLast,
}
}
Not Working
HTML
<input type="text" ng-model="shipNameFirst">
<input type="text" ng-model="shipNameLast">
<button type="button" ng-click="stripeBtn()">Checkout with Stripe</button>
Controller
$scope.stripeBtn = function(){
console.log($scope.shipNameFirst); //logging this (with $scope) comes up as undefined
$scope.details = {
recNameFirst: $scope.shipNameFirst,
recNameLast: $scope.shipNameLast,
}
}
Thanks!
Check the following code. It's working nicely.
var myApp = angular.module('myApp', []);
myApp.controller('myController', function($scope){
$scope.stripeBtn = function(){
console.log($scope.shipNameFirst);
$scope.details = {
recNameFirst: $scope.shipNameFirst,
recNameLast: $scope.shipNameLast,
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<input type="text" ng-model="shipNameFirst">
<input type="text" ng-model="shipNameLast">
<button type="button" ng-click="stripeBtn()">Checkout with Stripe</button>
</div>
SITUATION:
This is just an example of what I'm trying to accomplish in a real project, where I get an array of names from a web service, then I locate the inputs with those names, select them and then set their values using jQuery.
PROBLEM:
What I need is to know how to update the ng-model of those fields which I changed their value attribute using jQuery
I have tried these
Update Angular model after setting input value with jQuery
Angular model doesn't update when changing input programmatically
Update HTML input value changes in angular ng-model
...but I haven't had luck with any of those options.
I'm using AngularJS v1.4.8 and jQuery v1.11.1
I have tried setting the input type to hidden and type text with style: display:none but I can't get it working properly.
Here is a demo of what I'm trying to do. This has and input and an span bind with the same ng-model.
When you click the button, it's supposed to change the input value using jQuery and then update the ng-model.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
</head>
<body data-ng-app="app">
<div data-ng-controller="myCtrl as ctrl">
<span>Value: {{ctrl.myValue}}</span>
<input name="myId" type="hidden" data-ng-model="ctrl.myValue" />
<button data-ng-click="ctrl.changeValue('ValueChanged')">Change Value</button>
</div>
<script>
//my controller
angular.module('app', [])
.controller('myCtrl', function(){
var vm = this;
vm.wizard = {
changeValue: fnChangeValue
}
return vm.wizard;
function fnChangeValue(newValue){
var e = $('#myId');
e.val(newValue);
e.trigger('input'); //first option
//e.triggerHandler('change'); //second option
}
});
</script>
</body>
</html>
Fixed ID and added jQuery's change() which is probably what you tried to do. Below you can find your code fixed. And here is how this is usually done with AngularJS alone: https://jsfiddle.net/rwtm1uh9/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
<div data-ng-app="app">
<div data-ng-controller="myCtrl as ctrl">
<span>Value: {{ctrl.myValue}}</span>
<input id="myId" data-ng-model="ctrl.myValue" />
<button data-ng-click="ctrl.changeValue('ValueChanged')">Change Value</button>
</div>
<script>
//my controller
angular.module('app', [])
.controller('myCtrl', function() {
var vm = this;
vm.wizard = {
changeValue: fnChangeValue
}
return vm.wizard;
function fnChangeValue(newValue) {
var e = $('#myId');
e.val(newValue);
e.change();
}
});
</script>
</div>
You write var e = $('#myId'); and inside your input there is
<input name="myId" type="hidden" data-ng-model="ctrl.myValue2" />
I think you missed the id attribute try this instead :
<input id="myId" type="hidden" data-ng-model="ctrl.myValue2" />
Note: I did look around here on SO for solutions, yet no one had the additional issue of the function being in an object.
I have a form in my Angular JS app:
<div ng-app="plunker">
<div ng-controller="PMTController as pmt">
<form name="myForm">
<div class="form-group">
<input type="text" class="form-control" />
</div>
<button class="btn btn-primary" ng-click="pmt.search.resetSearchForm()">Reset</button>
</form>
</div>
</div>
Further, I have a controller with an object:
app.controller('PMTController', function($log) {
var _this = this;
_this.search = {
resetSearchForm: function () {
$log.debug('test');
// how to target the form?
}
};
})
My ng-click works, as the log.debug works. But no amount of tweaking to target the form so that I can reset the entire thing (empty all the fields) works.
I can do $window.myForm.reset(); but how could I do this from angular?
Note please my main issue/question is how to correctly target the form from inside that resetSearchForm function in the search object.
Note I tried changing the form name to pmt.myForm or pmt.search.myForm to no avail.
I tried $setPristine and $setUntouched() but they don't seem to clear the fields.
I know I can assign a model and assign it to all the form controls, but this is for a prototype so I'd rather do a simple reset.
I made a pen: https://codepen.io/smlombardi/pen/YWOPPq?editors=1011#0
Here is my take on your codepen that will hopefully resolve the issue:
https://codepen.io/watsoncn/pen/YWOXqZ?editors=1011
Explanation:
Angular's documentation provides an example of a "Form Reset" button, but you can apply the same logic towards resetting after submission:
Documentation:https://docs.angularjs.org/guide/forms
with a plunker:
Live Example:https://plnkr.co/edit/?p=preview
The example shows the use of Angular's copy method that creates a deep copy of whatever you pass it as a parameter and assigns it to the ng-model that is put on a particular input field. In this case they simply pass it an empty master object.
You need to make sure to add an ng-model attribute to your inputs, then create a reset function that can run after submission. Another common option would be to simply set each input's ng-model to empty strings in the submission function, such as $scope.inputModel = ""
Is this what you were hoping for? I might have misunderstood the question. I will happily take another crack at it if there is still confusion.
To get the form in your controller you just need to name your form this way:
<form name="pmt.myForm">
Here's a complete demo:
(function() {
"use strict";
angular
.module('plunker', [])
.controller('PMTController', PMTController);
PMTController.$inject = ['$log'];
function PMTController($log) {
var _this = this;
_this.model = {};
_this.search = {
resetSearchForm: function() {
console.log(_this.myForm); // -> Form reference
_this.model = {};
}
};
}
})();
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body ng-controller="PMTController as pmt">
<div class="col-md-12">
<form name="pmt.myForm">
<div class="form-group">
<input type="text" ng-model="pmt.model.example" class="form-control" />
<input type="text" ng-model="pmt.model.example2" class="form-control" />
<input type="text" ng-model="pmt.model.example3" class="form-control" />
</div>
<button class="btn btn-primary" ng-click="pmt.search.resetSearchForm()">Reset</button>
</form>
<hr> All fields:
<pre ng-bind="pmt.model | json"></pre>
</div>
</body>
</html>
I have a simple snippet of code :
function SomeCtrl($scope) {
$scope.modify = function(value) {
$scope.something = "Hello";
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="SomeCtrl">
<div ng-repeat="toto in [1,2,4,5]">
<input ng-model="something" />
<input ng-model="something" />
<button ng-click="modify()">Modify</button>
</div>
</div>
</div>
Does anyone can explain how I could change it so the modify() function only change the textfields inside the scope of the button I click ?
I also don't get why only the text fields which have not been edited are modified by the function.
Thank you very much
This is because ng-repeat creates it's own scope. Using prototypal inheritance. By declaring ng-model you're creating a new field on that new scope.
But this will work for what you're trying to do.
<div ng-repeat="toto in [1,2,4,5]" ng-init="something = {}">
<input ng-model="something.hi" />
<input ng-model="something.hi" />
<button ng-click="modify(something)">Modify</button>
</div>
</body>
.controller('ctrl', function ($scope) {
$scope.modify = function (something) {
something.hi = "hello";
}
})
In this case you are just pushing out on screen the same info for times, meanwhile binding everything to the same variable. You can just simply create array and bind every input line to appropriate array element. And by pressing "modify" button, pass parameter, witch array element must be changed.
function SomeCtrl($scope) {
$scope.something = [];
$scope.modify = function(toto) {
$scope.something[toto] = toto;
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="SomeCtrl">
<div ng-repeat="toto in [1,2,4,5]">
<input ng-model="something[toto]" />
<input ng-model="something[toto]" />
<button ng-click="modify(toto)">Modify</button>
</div>
</div>
</div>