angular material validate form by external event - javascript

I have a multi-part form, and I was hoping to have an external next/prev navigation for it. However, I need to be able to validate each part of the form when I navigate to next.
I have the following sample form definition:
<form layout="column" name="nProfileForm1">
<md-input-container>
<label>City</label>
<input ng-model="profile.city" required="" name="nCity">
<div ng-messages="nProfileForm1.nCity.$error" ng-if="nProfileForm1.nCity.$touched&&!nProfileForm1.nCity.$valid">
<div ng-message="required">City is required.</div>
</div>
</md-input-container>
</form>
If the field is interacted with,then validation is working find and error text is correctly shown. However, I cant figure out a way to trigger the validation of all the form fields if external event takes place. It seems somewhat wrong to add own submit button to every form part. What I am looking for is something similar to what schema-form does:
$scope.$broadcast('schemaFormValidate')
Any ideas would be appreciated.
Essentially, int he following example I want the field to light up with red once I press next:
http://codepen.io/Vladimir_M/pen/OWEjOd
UPDATE: updated codePen to include one solution that I've found.

After some attempts I've found one way to achieve the effect I was after with minimal code. Getting the form's scope and setting the form's $submitted property to true does the trick. It evaluates the entire form.
$scope.doSubmit = function(){
var formScope = angular.element(nProfileForm1).scope();
formScope.nProfileForm1.$submitted = true;
}
Feel free to suggest better ways.

Related

Controls Webpage with Knockout: Visible changes not saved

Trying to edit a website with Excel VBA. The edits appear to work, but when I use the save button, nothing is saved. Why isn't updated data, which is visible on the screen, being saved?
This code opens a web page in internet explorer, navigates where I want, fills out data, all which show on the screen, using various methods, such as:
For Each objElement In objElementColl
ExtractedName = objElement.outerHTML
If InStr(ExtractedName, "NewPermit") > 0 Then
objElement.Checked = True
and
Set DropDown = objHTML.getElementById("ProjectFile-AccreditedCertifierId")
DropDown.selectedIndex = 1
or
objHTML.getElementsByName(ElementName)(0).Value = ValueCheck
All work and changes appear on the screen. I click save by using:
Set objElementColl = objHTML.getElementsByClassName("btn")
For Each objElement In objElementColl
ExtractedName = objElement.outerHTML
If InStr(ExtractedName, "click: save, enable:") > 0 Then
objElement.Click
ExtractedName = 1
Exit For
End If
Next
Which runs. The issue is it doesn't save the changes from the three pieces above.
What I have tried
Pause my code and manually click save (same issue)
Pause my code, manually change a checkbox and run the code to save (does save the manual change, but not the coded ones
Pause the code and manually change a box and manually save (only manually changed box is saved)
From above, it appears my save click works, but although the boxes are visibly changed and filled out using the code, there is a gap between the visible and the background.
Some HTML source code. Is what Chrome shows me when Inspecting an element I am changing:
<fieldset>
<legend>Proposal</legend>
<div class="col-xs-12 col-sm-8 col-md-6">
<div class="row">
<div class="col-xs-2 form-group">
<label for="ProjectFile_ProposalLot">Lot</label><input class="form-control" data-bind="textInput: ProjectFile().ProposalLot" maxlength="100" name="ProjectFile-ProposalLot" type="text" />
</div>
<div class="col-xs-2 form-group" data-bind="visible: ProjectFile().StateId() != 7 && ProjectFile().StateId() != 5">
<label data-bind="text: ProjectFile().ProposalDpLabel()"></label>
<input class="form-control" data-bind="textInput: ProjectFile().ProposalDp" maxlength="100" name="ProjectFile-ProposalDp" type="text" />
</div>
I searched the source code for the page. I believe this might be important, but I am not a HTML coder. I have shortened it a bit
var ProjectFileEditViewModel=(function(){__extends(ProjectFileEditViewModel,ViewModel.Model);function ProjectFileEditViewModel(){ProjectFileEditViewModel.__super__.constructor.apply(this,arguments);};ProjectFileEditViewModel.prototype.fields=function(){return {"Id":new ViewModel.NumberField(0),"StateId":new ViewModel.NumberField(0),"DefaultOfficeAddressId":new ViewModel.ObservableField(),"Name":new ViewModel.ObservableField(),"ExistingApprovalDate":new ViewModel.DateField("DD/MM/YYYY"),"ProjectClosed":new ViewModel.ObservableField(),"ProposalAddress":new ViewModel.ObservableChildField(exports.AddressViewModel,this),"Zoning":new ViewModel.ObservableField(),"ProposalLot":new return ProjectFileEditViewModel;})();if(exports.ProjectFileEditViewModel==null)exports.ProjectFileEditViewModel=ProjectFileEditViewModel;
There is also this:
Buildaform.model=new Buildaform.ProjectPageViewModel({ ... ,"ProposalLot":null .... }
I think this last one has something to do with it. I do not know if I can change it.
I cannot release the website address or source code publicly.
As the regarding web site can not be shared, I can come up with a just set of hints to try out:
If the web site would implement a simple (pure) HTML form to send the POST request, your solution would be fine. But looking at the HTML you shared
<label data-bind="text: ProjectFile().ProposalDpLabel()"></label>
the data-bind is already suggesting that the data is getting collected/sent by a library. (E.g. Knockout is using that attribute). This library might now collect the data somewhere, and it might get triggered by a "click" or a "key" event in JavaScript. The collected information can then be stored in a hidden DOM element as suggested by GCSDC or directly in a JavaScript variable.
What I would suggest now is to find out which JavaScript framework is used on this page by inspecting the HTML source. At some point there should be a
<script src="<fancy js framework>.js"></script>
tag in the HTML, which should give you the name of the framework. (There can actually be multiple tags of this kind, including custom JavaScript files. These tags do not have to be at the beginning of the HTML document, and can be scattered all over it, so you might have to search for script in the HTML document. One of them should be the main framework, which is sending the request. If you are not sure which one it would be, you have to google all of them and find out.)
Then, research how the the POST (maybe Ajax) request is sent in the JavaScript code on this page, with help from the documentation of the Framework. And then, send the request by executing custom JavaScript from VBA on this page; how this could be done is shown in this post.
Alternatively, you could try to trigger a click (or key) event on the form inputs to make the framework believe you actually typed it in; how this could be done is shown in this post, but this might not work in all cases.
Per your comment that:
Pause my code, manually change a checkbox and run the code to save
(does save the manual change, but not the coded ones
It seems that the problem is with the code setting form controls and not with the code clicking the save button.
This seems to be a problem not related to VBA but with the behaviour of knockout - see this SO post. The pertinent comment is:
Your problem is that ko subscribes on the click event inside the checked binding:
The questioner in that post is having a similar problem to you - they are trying to check a checkbox (to change the view) but it is not updating either the viewmodel, or the underlying model itself. Knockout is a MVVM framework.
The give-away in your question is that your manual changes commit because you perform a click-and-change when performing the action via point-and-click in the browser, but your programmatic method only does the change to the form control, but not the click first.
So, how to solve this via VBA automation through IE?
Based on the solution in the post I referenced above, plus the method here I will hazard the code below as a possible solution, but please note it is untested ...
Basically you need to 'click' on the form element you want to change - and then update the control value. Hopefully the 'clicking' bit will mean that the knockout viewmodel updates per the 'change', and from there, the model data will be written to the database (or whatever):
Your checkbox example:
If InStr(ExtractedName, "NewPermit") > 0 Then
// hopefully this will get knockout to apply the required binding before your change the value
objElement.Click
objElement.Checked = True
Your dropdown example:
Set DropDown = objHTML.getElementById("ProjectFile-AccreditedCertifierId")
// hopefully this will get knockout to apply the required binding before your change the value
Dropdown.Click
DropDown.selectedIndex = 1
Hope that helps - quite the 3-pipe problem! Good luck.

onBlur on editable-form (Angularjs)

Is there a directive onblur for editable-form? I can't seem to find one. angular has this ngTouch but it only validates a single input. What I really want is to know if the user loses focus on the form itself.
my code is something like this [editable-form][1]
but when the user clicks on the different form the editable form will trigger the editableForm.$cancel() method.
http://jsfiddle.net/NfPcH/81/
I've got the solution, you only need to add the tag blur='cancel' on <form editable-form name="editableForm" onaftersave="saveUser()" blur="cancel">

parsley.js - clear error message when using CKEditor

I have spent several hours trying to get this issue to work, but I am getting nowhere fast, so I am hoping some one can assist me. I have tried many attempts, searched StackOverflow and Google.
I have a form with a textarea. I have implemented parsley.js on to a form. The parsley validation is working fine, until I add in the CKEditor to the textarea.
The issue I have is that the parsley error message persists (is always displayed) when I submit the form with no value in the CKEditor, even after I enter characters into the CKEditor.
How do I clear the parsley error message when entering data into the CKEditor
I think the reason is that there is no onKeyUp action on the textarea, because the onKeyUp action is now operating on the CKEditor and the textarea is hidden, but then not being able to remove the parsley required error message when I enter data into the CKEditor is killing me.
Here is my form:
<form id="details_form" class="form-horizontal" method="post" data-parsley-validate>
Here is the textarea code:
<p>
<textarea rows="10" data-parsley-required="true" data-parsley-maxlength="5000" data-parsley-required-message="This field is required." id="id_field" cols="40" name="field" data-parsley-id="8686" dir="ltr"></textarea>
<span class="parsley-errors-list" id="parsley-id-8686"></span>
</p>
Any help would be great.
I had the same problem. So here is the solution ;)
HTML:
<textarea id="ckeditor" data-parsley-required="true" data-parsley-required-message="This field is required" rows="6"></textarea>
JS:
CKEDITOR.replace( 'ckeditor' );
CKEDITOR.config = {
autoUpdateElement: true,
}
CKEDITOR.on('instanceReady', function(){
$.each( CKEDITOR.instances, function(instance) {
CKEDITOR.instances[instance].on("change", function(e) {
for ( instance in CKEDITOR.instances )
CKEDITOR.instances[instance].updateElement();
});
});
});
Edited due to comment by mightyspaj:
CKEditor does not actually operate ontop of the textarea element. The element gets replaced by an iframe to provide the UI. This problem sounds like the textarea is not being updated properly.
I suggest that you access the textarea by JavaScript and manually trigger different events on it to see if the validation message changes due to those triggers. Parsley might have the events it listens to documented somewhere.
When you find for sure the offending event, simply bypass the automation and fire it yourself. If you need live refreshing do for example a 1second setInterval to trigger the validation.
Old answer:
Sounds like you want the autoUpdateElement configuration setting: http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-autoUpdateElement
CKE does not operate directly on the textarea, it creates an iframe and does some other magic. So, the underlying element needs to be updated. You can do this manually using the updateElement() function or you can try autoUpdateElement setting above.

IE compatible outer input referring form

Situation
I have a form
<form action="." method="POST" id="my_form">
<!-- Form stuff here -->
</form>
<p onclick="confirmUpdate();">Update</p>
The confirmUpdate() function generates a confirmation message and the following input tag:
<input type="submit" name="my_name" value="Yes. Update the data.">
using the following JavaScript:
inputYes.type = 'submit';
inputYes.name = 'my_name';
inputYes.value = 'Yes. Update the data.';
inputYes.form = 'my_form';
The page is created as intended, but the input element has no form="my_form" on it.
Condition
The HTML generated with Javascript has to be shown as a nice "HTML pop-up" (not an alert box) to ask the user if the info is correct before submitting.
Questions
Why isn't it working?
The JavaScript generated HTML doesn't appear on the Page Source. Will it be able to submit the data from the form?
Thank you in advance.
You should use setAttribute instead:
inputYes.setAttribute('form', 'my_form');
If the goal is to get your input button to work, then inside your method confirmUpdate(), make the following additions/changes:
Updated fiddle here: http://jsfiddle.net/B7QAc/4/
//add this
var theform = document.getElementById('my_form');
//change this
document.body.appendChild(screenDiv);
//to this
theform.appendChild(screenDiv);
While the previous answers were correct, I found a better solution for my problem. I had to update the question in order to make it more clear. The HTML generated with Javascript was intended to show as a nice "pop-up" to ask the user if the info is correct before submitting.
Therefore, the <input> tag has to be outside of the <form> and reference its id="my_form" via a form="my_form attribute.
Here is the updated JSFiddle for it.
While inputYes.form = 'my_form'; doesn't add the form attribute, inputYes.setAttribute('form', 'my_form'); does the job.
Notice though that it only works at the end of the script, only after it is appended to the HTML Document. It would not work otherwise (at least in this script).
Even though I lack the technical knowledge to explain it better, those are my observations.
This would be the accepted answer. I will promptly accept any other answer that is more complete than this one.

Change an input value and submit the form on keypress (not just enter to send)

I'm really confused. I want to make a sort of a hotkey that changes the value of a hidden input field and submits the form. How can I do that? I've read numerous blogs and tutorials but all assume that I just want to submit the filled form after pressing enter. While I just don't understand how the very "structure" of a form acts in javascript.
Should I fill the hidden input like this:
document.getElementById('foo').value='bar'
I don't think there's even a way to see if its value was changed so I'm not sure.
And then, how do I submit the form, if I have:
<form name='myform' method='post' action='url.html'>
I tried document.myform.submit() and document.myform.form.submit(), and I've also tried giving the form an id and using document.getElementById('myformid').submit() but none of these work! I usually get the error TypeError: 'undefined' is not an object.
I'm new to javascript, I'm used to working with python but it has a completely different philosophy, and maybe that's the source of my confusion. I'd very appreciate some explanation, not just a code snippet.
Thanks!
You can always check the hidden field with the Development Tools of your Browser - just press F12 and you will see it. Go to the DOM list (within the Development Tool) and then you see the actual value of that field.
To submit a form via JavaScript normally document.name.submit() is enough. Another option is that you use e.g. jQuery to submit a form via AJAX (with the help of jQuery.serialize)
If you want to use document.getElementById('myformid').submit() you have to give an ID to your form like that :
<form name='myform' id="myform" method='post' action='url.html'>
It's the same thing about your hidden field.
document.getElementById('foo').value='bar' assume you have an hidden like that :
<input type="hidden" name="foo" id="foo" />
You can try the following approach
<form name='myform' method='post' action='url.html'>
// your fields here
// then use a input type button to have a button and define an on click event
</form>
<script type = "text/javscript">
use the event in your script
//change your hidden field value here and
// submit the form by
myform.submit();
</script>
You can use ajax or jquery as there is a function named on key up it means after pressing a key on the last field which ever you choose as you leave the key on keyboard it will submit the forms.
check this okay http://www.w3schools.com/php/php_ajax_livesearch.asp

Categories