I'm trying to validate a form that was included using ng-include.
HTML:
function submit() {
if($scope.form.$invalid) {
return;
}
}
$scope.submit = submit;
<form name='form' ng-submit="submit()" novalidate>
<div ng-include="'my_form_inputs.html'"></div>
</form>
when i try to submit i get an error that form.$invalid is null.
i know ng-include creates another scope within the controller's scope, but is there no way to validate this form?
it seems like i would have to duplicate the entire form elements if i want to create an edit page for this form.
any idea?
Related
I have a form inside a modal pop up. I am trying to run form validation on the inputs after the user attempts to submit the form. So far, I'm struggling to make things work.
In my view, I have the following (sorry if there are any syntax errors, I'm converting this from jade on the fly):
<script type="text/ng-template", id="modalVideoNew">
<div class="ngdialog-message">
<form class="form-horizontal" ng-submit="submitForm()" novalidate name="newVideoForm">
...
<div class="form-group">
<label> Title </label>
<div class="col-sm-8">
<input type="text" name="title", required='', ng-model="newVideoForm.title">
<span class="text-danger" ng-show="validateInput('newVideoForm.title', 'required')"> This field is required</span>
</div>
</div>
</div>
</script>
And then in my controller, where I'm calling the ng-dialog pop up, I have this:
$scope.newVideo = function() {
ngDialog.openConfirm({
template: 'modalVideoNew',
className: 'ngdialog-theme-default',
scope: $scope
}).then(function() {
$scope.validateInput = function(name, type) {
var input = $scope.newVideoForm[name];
return (input.$dirty || $scope.submitted) && input.$error[type];
};
var newVideo = $scope.newVideoForm;
...
Right now, I am still able to submit the form, but once I open it back up I see the 'This field is required' error message. Also, the input is pre-filled with [object, Object] instead of an empty text input box.
A way of cleaning your model would work with using a model var that belongs to your parent controller and cleaning it in the callback. Check out how the template has attached your parent controller's var FormData.
Check this out
So about your validation, what I would recommend you is to have your own controller in it, no matter how much code it will have. It helps you keeping concepts of modularization and a better control over your scopes. This way will also facilitate a lot when validating.
I don't if this is something I did, but once I upgraded to Angular 1.3, the form is no longer defined in my scope. My HTML is
<div some-dir>
<form name="myForm">
<!-- Form stuff here -->
<button ng-click="submit();">
</form>
</div>
The submit function is
scope.submit = function() {
console.log(scope.myForm);
}
And this returns undefined. I have no ng-if or ng-repeat anywhere. There is only one directive and one scope in this specific directive. Again, this was all working until I upgraded to Angular 1.3
The problem can be solved by scoping form data into some scope object:
<form name="myForms.firstForm">
<!-- Form stuff here -->
<button ng-click="submit();">
</form>
And than:
scope.myForms = {};
scope.submit = function() {
console.log(scope.myForms.firstForm);
}
Some more info in this comment.
In my case it happened that my form was nested within another form.
So once I switched the <form name="myForm"> to <ng-form name="myForm" ...> the form was defined.
See ng-form docs.
Got the same problem and fixed by declaring the controller in the html template that contains the form. So you form declaration would become:
<form name="myForm" ng-controller="SomeController">
New "feature" of 1.3, probably..
So I'm generating form HTML on the server and serving it up via an API for angular to use. The reason for this is that the forms need to be generated by server-side plugins. This may not be the best way do to it for Angular, but I'm asking whether it will be possible...
template.html
<form>
<div ng-bind-html="form"></div>
<button ng-click="save"></button>
</form>
directive.js (abridged)
ExtensionManagementService.getConfiguration({
extension_id: $scope.extension.id,
configuration_id: configuration.id || null
}).$promise.then(function(data) {
$scope.form = $sce.trustAsHtml(data['form']);
$scope.configuration = data.data;
})
The code above binds successfully into the div and I can see the form as I expect.
Example markup:
<p>
<label for="id_name">Name:</label>
<input id="id_name" name="name" ng-model="configuration.name" type="text" />
</p>
I have a save event that passes the scope.configuration into a controller which I then console out the values.
However configuration.name is always blank, I expect because angular hasn't registered the binding of the inserted markup.
Is there a way to essentially give Angular a nudge?
As #originof suggested, and a colleague almost beat him to it, the $compile module is the key to this:
ExtensionManagementService.getConfiguration({
extension_id: $scope.extension.id,
configuration_id: configuration.id || null
}).$promise.then(function(data) {
var form_element = $element.find('div[role="form"]');
form_element.html(data['form']);
$scope.configuration = data.data;
$compile(form_element.contents())($scope);
});
I currently have a form like the following:
<form autocomplete="on" enctype="multipart/form-data" accept-charset="UTF-8" method="POST" action="{{trustSrc(SUBMIT_URL)}}">
<input type="text" name="firstinput" ng-model="first"/>
<input type="text" name="secondinput" ng-model="second"/>
<input type='submit'/>
</form>
And a controller like so:
$scope.first = "first";
$scope.second = "second";
$scope.SUBMIT_URL = DATABASE_URL + "forms/submit/";
$scope.trustSrc = function(src) {
return $sce.trustAsResourceUrl(src);
};
And when I submit this form as is, it works just fine with the backend. However I now need to use ng-submit in place of the standard HTML form submit because I need to run a find and replace in $scope.first. The backend expects the data to be posted exactly in the way the original HTML form does. How do I use $http or $resource to post in the exact same format as the HTML form?
It is not very clear what you are trying to accomplish. But, you should tidy up your code a bit, to make the implementation easier:
Don't use different variables for each input's field. Instead, use an object with different keys.
Use ng-click (or ng-submit) for your submission. Action will go inside your JS logic.
Use the novalidate attribute so that Angular can properly format, and validate your form on its own (and you don't get confusing cross-browser effects).
With those in mind, your new markup would be:
<form autocomplete="on" enctype="multipart/form-data" accept-charset="UTF-8" novalidate>
<input type="text" name="first" ng-model="form.first" />
<input type="text" name="second" ng-model="form.second" />
<button ng-click="submit">Submit</button>
</form>
Your JS directive is then:
app.directive('form', function($http)
{
return function(scope, element, attrs)
{
// Leave this empty if you don't have an initial data set
scope.form = {
first : 'First Thing To Write',
second : 'Second item'
}
// Now submission is called
scope.submit = function()
{
// You have access to the variable scope.form
// This contains ALL of your form and is in the right format
// to be sent to an backend API call; it will be a JSON format
// Use $http or $resource to make your request now:
$http.post('/api/call', scope.form)
.success(function(response)
{
// Submission successful. Post-process the response
})
}
}
});
I have the following form in my AngularJS app which contain hidden fields with values filled based on user selection on some inputs on the form (radio buttons...etc), when the user click on the Submit link I should route the user to an external URL while passing hidden fields just as any normal form submission. Unfortunately I can't do this as some of the hidden field values are dependent on some calculations inside a function of the view related controller (as shown below in controller code, so I was wondering is there a way I can call the controller function from this form, then the controller function post the whole form and its field? Any example is highly appreciated. Thanks.
Note I am using link instead of a button.
<form name="clientPaymentForm" id="clientPaymentForm" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">>
<div>
<fieldset>
<input id="name" type="text" required placeholder="Client Name" ng-model="client.name">
...
...
<input type="hidden" name="amount" ng-value="order.total">
...
...
<a class="orderButton" href="javascript:{}" onclick="document.getElementById('clientPaymentForm').submit(); return false;">Order Now</a>
</fieldset>
</div>
</form>
Controller:
$scope.processOrder = function(){
//Order calculation happens here to update order.total value and can only happen after click click Order Now to place the order...
};
I guess this is a bit late, but what you want to use is the ng-click directive which will allow you to call functions defined directly on the scope.
Assuming that you've defined $scope.processOrder, change your a tag to the following:
<a class="orderButton" ng-click="processOrder()">Order Now</a>
And everything should work as hoped.
Alternatively, you could use ng-submit on the form to have it work when you press the "Enter" or "Return" key, as in:
<form name="clientPaymentForm" id="clientPaymentForm" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top" ng-click="processOrder()">.