Set form as $pristine, but keep current values - javascript

My use case is that I need to enable/disabled a save button based on if the user has changed the values of a form.
When the user clicks the save button (after making changes) an AJAX save will occur, and on complete of that the form needs to be considered "pristine" again, but keep the current values.
I figured setting form.$pristine = true would work, which it does the first time after clicking the button, but editing the values from there doesn't set $pristine to false.
Example plunker: http://plnkr.co/edit/VX2R1bdGJFdzH3LEsNnB?p=preview
<form name="submitForm">
<input ng-model="data.first" type="text" />
<input ng-model="data.second" type="text" />
</form>
<button ng-click="saveForm()">Submit</button>
<div>Form pristine: {{submitForm.$pristine}}</div>
//In controller
$scope.saveForm = function(){
$scope.submitForm.$pristine = true;
}
Is there another way of doing this?
If not, what do I need to do to get this to work?

FormController.$setPristine();
Sets the form to its pristine state.
This method can be called to remove the 'ng-dirty' class and set the form to its pristine state (ng-pristine class). This method will also propagate to all the controls contained in this form.
Setting a form back to a pristine state is often useful when we want to 'reuse' a form after saving or resetting it.

I would recommend ng-submit on the form tag rather than using ng-click. ng-submit makes sure all viewmodel changes are committed before event handler for ng-submit is called. This will apply specially if you are using ng-options with ng-model where you might have set options to set model to update only after certain time or onblur.
you can also do set the value of form to pristine on submit in markup like this
Here is the updated code and plunker. note that ng-submit will not get called if form is not valid. This is another advantage of using ng-submit over ng-click.
<form name="submitForm" ng-submit="saveForm();submitForm.$setPristine();">
<input ng-model="data.first" type="text" />
<input ng-model="data.second" type="text" />
<button >Submit</button>
</form>
http://plnkr.co/edit/2bWvPm9xNoVPFKYUhdUM?p=preview

Related

How to Completely Prevent Web Form Input Text Item change

I have this simple web-form
<form id="MyFormDiv" method="post">
<input type="number" name="cmp_no" id="id_cmp_no">
<input type="text" name="cmp_lname" maxlength="40 id="id_cmp_lname">
<input type="submit" name="submit" value="Save" id="submit-id-submit">
</form>
and this form will be used for both add and update.
When insert I have no problem, but when update I don't want to allow user to update or change the value of item which its id= "id_cmp_no"
I used javascript code to set its readonly property to true but that was not the 100% solution, because user can use browser inspect tool and see page source and change it's value before submitting the form, and therefore the readonly property is not useful.
Can I override it's onchange event to prevent change of it's value even if the value changed from page source using inspect tool.
Any one can help, thank you in advance
There is nothing that stops a user from changing values in browser, u can try solutions given in the above answers but be cautious user can dig out number of ways to do so like by using firebug/inspect element/ what ever..
What we can do is checking our values on server side and prompting user if they mismatch.
Shouting again ..
Never trust/depend on client....
If a user is skilled enough to open dev tools and change values from there, chances are they can also alter any JS code that prevents editing the readonly value.
So, there is no substitute to proper server-side validation.
You could check that the value is not being altered from the form's onsubmit event handler (see below), but keeping in mind what I and many commenters stated above.
$("form").on("submit", function(e) {
//check value of the input
if(this.someInput.value != 1) {
//do something here
//return false; if you want to block submit
}
return true;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form">
<input type="number" name="someInput" readonly value="1"/>
<button type="submit">Submit</button>
</form>

Angular: how to reset form elements that map to different data

My angular app has > 1 forms on a page. Each form can be saved or reset. The fields on each form don't necessarily map to its own data object.
For example I have two pieces of data that must be gotten and saved separately. Let's call the json chunks, a and b.
HTML:
<form>
<input type="text" ng-model="a.foo"/>
<input type="text" ng-model="b.bar"/>
</form
<form>
<input type="text" ng-model="b.bar[0].baz"/>
<input type="text" ng-model="a.boo"/>
</form
If the first form were mapped to just a and the second to b it would be a simple matter of resetting the data. But I don't want to reset all the a or b data for all forms on the page. I just want to reset the specific data fields for the inputs represented on a particular form.
My current logic mostly works. On cancel I get the elements in the form, get their ng-model attributes and dynamically reset properties on a and b depending on the ng-model string value. This seems "dirty" and plus it doesn't work for some ng-model attributes which use the $index special variable because the attr value isn't parsed by angular when doing .attr(). What's the best solution for this? Different models for each form that map back to the original data?
Make a deep copy of the object you are editing when opening the form and edit it ( angular.extend)
when save just use your save logic
on cancel you will need to do nothing
e g
.controller('myctrl', function($scope, dataService) {
$scope.data = angular.extend( {}, dataService.get())
$scope.save = function ( ) {
dataService.set($scope.data)
}
})
I haven't done this before, but you can try having something like below:
<form>
<input type="text" ng-model="form1.element1" ng-change="a.foo=form1.element1"/>
<input type="text" ng-model="form1.element2" ng-change="b.bar=form1.element2"/>
</form>
<form>
<input type="text" ng-model="form2.element1" ng-change="b.bar[0].baz=form2.element1"/>
<input type="text" ng-model="form2.element2" ng-change="a.boo=form2.element2"/>
</form>
to have an easy reference to your form-specific elements. And then for resetting, you can simply reset the form1 or form2 objects with initial values using angular.copy().
One thing you may need to watch with this approach is, once you enter some values and reset although on the form1 or form2 will be reset, there may still be values in a and b objects, you might want to handle that (disable submit for e.g.)

Why is Symphony CMS not saving the empty input value as such when submitting form via jQuery?

I have the following HTML form, which allows a user to optionally save a custom label for their product.
<form action="http://domain.com/members/systems" method="post" class="mod-SystemLabel-EditForm">
<label class="mod-SystemLabel-EditLabel" for="label-623">Customer label</label>
<input type="text" value="sdff sdf sd" name="fields[customer-label]" class="mod-SystemLabel-EditInput" id="label-623">
Clear
Cancel
<input type="submit" value="Save" name="action[system-edit-label]">
<input type="hidden" value="623" name="id">
</form>
If I manually clear my text input and submit my form, Symphony CMS records the empty value as expected.
If I use jQuery to trigger the form submission as below, Symphony CMS leaves (or re-saves?) the current value as it was.
$('.mod-SystemLabel-OtherButton-clear').click(function(e) {
e.preventDefault();
$(this).siblings('.mod-SystemLabel-EditInput').val('');
//alert($(this).closest('form').serialize());
$(this).closest('form').submit();
});
If I uncomment the commented line, the alert contains:
fields%5Bcustomer-label%5D=&id=623
This serialization is the same as what is produced when I backspace the input myself, so it looks like the actual form submission should be the same as a manual input clearing and click of the submit button.
The Symphony field is not set to be required and does not have any validation rules.
Why is the end result different and how can I get the empty value to be saved, overwriting the previous product label?
The form’s submit input’s name is not passed when the form is submitted via JavaScript, and Symphony CMS uses this to trigger the appropriate event.
To get the event name passed along with the submit input, trigger a “click”.
$('.mod-SystemLabel-OtherButton-clear').click(function(e) {
e.preventDefault();
$(this).siblings('.mod-SystemLabel-EditInput').val('');
$(this).siblings('input[type=submit]').trigger('click');
});

Delay form submit (AngularJS)

How can I prevent submitting a form in Angular until I receive a callback?
I have something along these lines:
<form method="post" action="http://example.com/external" ng-submit="submit()">
<input type="hidden" name="foo" value="{{bar}}" />
<input type="submit" />
</form>
Before submitting the form, I need to get the {{bar}} value from a local API call (using $http), and place it in the scope before allowing the actual form to submit (not POSTed using $http). How can this be done?
The form directive in Angular will wrap it in a formController and intercept it. You can still run your asynchronous code but you will need to reference the DOM form to submit it. I have an example fiddle with the solution - basically it sets up a button to submit the form, asynchronously sets the hidden field, then posts it.
Here is the relevant code:
MyController = function ($scope, MyService) {
$scope.boo = "";
$scope.submit = function () {
MyService.getAsync().then(function(result) {
$scope.boo = result;
document.myForm.action = "http://example.com/";
document.myForm.submit();
});
};
};
If you run a fiddle you will see the hidden field is populated:
http://jsfiddle.net/jeremylikness/T6B2X/
The "ugly" part of the code is the direct reference to:
document.myForm
If you wanted to clean this up, you could write your own directive that allows you to place an attribute on the form and interacts with a service to manipulate it. I.e. MyFormService and then I could do MyFormService.setAction(url) and MyFormService.submit() - that would be more cleaner and reusable but time wouldn't permit me to set that up for you.
As docs for ng-submit state:
Additionally it prevents the default action (which for form means
sending the request to the server and reloading the current page) but
only if the form does not contain an action attribute.
So remove that action attribute and handle it directly yourself in the submit() handler on the scope.
Make yours http call and in then success handler submit the form manually.
Can you not just use the submit button's onClick event to call a function that returns false if the submit is not allowed?
i.e. onClick='return CheckIfFooPopulated();'
Then in that function return false is foo as not yet been set or true if it OK to submit.
The problem is that ng-submit doesn't work with an action attribute, as stated in the docs.
Then, you can do whatever you want inside of submit() in your controller. However, I would use ng-model for the form input fields because it gives you better control over the model.
You would use this $scope.formModel to bind the input fields to the scope.
You could implement submit like that:
$scope.submit = function() {
$http.get("URL").success(function(data) {
$http.post("URL2", { model: $scope.formModel, bar: data.bar }).success(function() {
$location.path("/new-route");
});
});
}
There many possibilityes, but a less risky is to use ng-switch.
ng-switch do not load DOM if not needed.
<span ng-switch on="barNotEmpty">
<span ng-switch-when="true">
<form method="post" action="http://example.com/external" ng-submit="submit()">
<input type="hidden" name="foo" value="{{bar}}" />
</form>
</span>
<span ng-switch-default>
<form>
<input type="hidden" name="foo" value="{{bar}}" />
</form>
</span>

How to update/change HTML content with JavaScript and prevent the page from refreshing?

I'm a newbie to scripting. I want to update HTML content with JavaScript, but as you can see
the web page keeps refreshing.
How can I prevent the page from refreshing?
Javascript:
function showResult(form) {
var coba=form.willbeshown.value;
var coba2=coba+2;
document.getElementById("showresulthere").innerHTML=coba2;
}
HTML
<form>
<input type="text" name="willbeshown" value="">
<button onclick="showResult(this.form)">Ganti1</button>
</form>
<p id="showresulthere">Result will be shown here</p>
</body>
Don’t use a form at all. You are not submitting any form data to a server. To process data in the browser, you don’t need a form. Using a form just complicates things (though such issues could be fixed by using type=button in the button element, to prevent it from acting as a submit button).
<input type="text" id="willbeshown" value="">
<button onclick=
"showResult(document.getElementById('willbeshown'))">Ganti1</button>
<p id="showresulthere">Result will be shown here</p>
<script>
function showResult(elem) {
document.getElementById("showresulthere").innerHTML = Number(elem.value) + 2;
}
</script>
I have used conversion to numeric, Number(), as I suppose you want to add 2 to the field value numerically, e.g. 42 + 2 making 44 and not as a string, 42 + 2 making 422 (which is what happens by default if you just use an input element’s value and add something to it.
Your button should be
<button onclick="showResult(this.form); return false;">Ganti1</button>
Javascript
function showResult(form) {
var coba=form.willbeshown.value;
var coba2=coba+2;
document.getElementById("showresulthere").innerHTML=coba2;
return false; // prevent form submission with page load
}
DEMO
The others will explain how you should use jQuery, but this would explain why it didn't work in your original code.
The <button> tag submits the form, so you have to add this inside your form tag to prevent form submission:
<form onsubmit="return false">
Btw, even without giving your form an explicit action, it uses the current page to submit; it's easy to think that it will not do anything without an action.
If you define a <button /> without defining its type it will work like a submit button. Just add type="button" to your button markup and the form won't be submitted.
<button type="button" onclick="showResult(this.form)">Ganti1</button>
With this change you won't need any return false or .preventDefault() "workarounds"

Categories