Submittable HTML5 Web Component - polymer-1.0

How do I create a form-submittable web component?
Background:
I have a customer-picker component that is basically a text input plus a tiny button to the right of the text box plus a dialog that pops up when the button is clicked. It is used in the same way as one might use an html select.
This component is used as part of an html form that is submitted in the old fashioned (non-ajax) kind of way. The actual html input is encapsulated privately inside of the customer-picker component.
Problem:
The text input's value is not submitted
I guess I can understand why this is. I suppose this is the desired behavior (otherwise we are breaking encapsulation).
So with all that said, how do I create a submittable web component?
For example, suppose I have a form like this:
<form action="action.jsp">
<input name="date-start"/>
<input name="date-end"/>
<input name="name-first"/>
<input name="name-last"/>
</form>
that gets submitted like this:
action.jsp?date-start=2016-06-01&date-end=2016-06-30&name-first=Joe&name-last=Smith
I would like to create the same form using components like this:
<form action="action.jsp">
<date-range name="date">
<full-name name="name">
</form>
that gets submitted exactly the same way as the example above:
action.jsp?date-start=2016-06-01&date-end=2016-06-30&name-first=Joe&name-last=Smith
I am aware of iron-form. But this solution has some problems.
For one, it does not emulate native form submission very well. In a normal html form, when you submit, the current page is automatically replaced by whatever is returned by the action URL. This doesn't seem to happen with iron-form.
Second. It only allows your component to contribute a single value to the submitted data. In the above mentioned date-range example, I would like two values to be submitted for one component.

Related

AngularJS - memorizing chosen values in form after returing from some special state (view)

I build some form analogously to:
http://tutorials.jenkov.com/angularjs/forms.html
It means that I also use ng-model as chosen value. These values are retrieved from database - there are multiselect options.
<form>
<input type="text" name="firstName" ng-model="myCtrl.firstName"> First name <br/>
<input type="text" name="lastName" ng-model="myForm.lastName"> Last name <br/>
</form>
Controller {
constructor() {
this.firstName = getFirstNameFromDatabase();
}
}
It is sketch of my code - I wouldn't like to show it here.
It is working ok - values are retrieved from database and displayed as proposition in form.
My issue is following:
Let's assume that someone type in this form "abc". Then, someone click button next (it direct to another state, user is directed to another view - lets denote it X).
User can return from X view with back button. I would like to display "abc" (so my app should memorize chosen values).
However, if user type value "abc" and return to menu (or another else state (view) - different from next button) - in this case value shouldn't be memorized.
Can you give me some clues ?
Since you're actually switching pages in your application, you're going to have to put their content in some sort of persistent storage. A couple ideas pop into my head.
Temporary Browser Storage / Cookies
Server-side storage in a Database or Cache
Either way, you'll need to store the data whenever the user manipules the values. And when they switch pages, choose whether to clear the data or not based on whether it's your special view.
Or another idea is to use an angular function to change the url (rather than a simple anchor). Then in that function you can persist the data before switching to your view. But if they go to a different page, it won't get saved. This only works if they navigate based on your page's links.
Usually this sort of thing is accomplished using a single page which includes both your original view and the next view. You can swap out the content using JS so the user doesn't know the difference. So that's still an option too.

Is there any way I can direct focus to a specific input field on a form?

I have a large form and I would like when the user clicks a "new" button for the focus to be placed in a specific input field. There's a grid on the form and every field has a known id. Note it might not be the first field so not easy to use the tab.
Would appreciate some advice if this is possible. Would save having to manually have the user move the cursor over and click in the input field.
Update: Changed "move cursor" to "change focus"
Here is one solution -
Angular js gives you an advantage of using some of the extra features so that you dont have to use the jquery.
Here is one way to implement the autofocus feature.
<div class="button" input-focus>{{element.idORname}}</div>
and the directive to be defined here.
.directive("inputfocus",function($timeout){
return {
link : function(element,attributes){
element.bind('click',function($timeout){
$timeout(function(){
element/*.parent() or.child()*/.find('type of the field you want to select')[0].focus();
);
);
);
Here you can use the javascript or jquery methods for the dom traversal if there are nested fields in your code.
$timeout is necessary to call for the focus after the browser renders when user has finished clicking the event
As you can see the find('')[0] is a replacement for find('').focus as the latter requires jquery to be used.
Place "autofocus" attribute on the element that you want to focus.
Example:
Name: <input type="text" name="name" autofocus />
If all the input ids are known, just use that.
$("#NewButton").on('click', function(){
//Other code.
$("#IdOfInputToBeFocused").focus();
});
Custom data attribute can be used with jQuery like this
<input data-field="special" />
And then that specific field can be called like this
jQuery('input').find("[data-field='special']").focus();

AngularJS - Form validation triggered on load

I added field validation attributes like "required" and "pattern" in my form, and the form is inside a ng-controller. The validation works. But it seems the validations are triggered on page load, and I see all the fields are marked as invalid with error message when the page load.
I tried to add "novalidation" attribute to the form as indicated in the examples on AngularJS website, but no luck.
I would like to have the validation triggered the first time the user tries to interact with it. How can I do that?
Update
Here's an example https://jsfiddle.net/davidshen84/00t197gx/
<div class="mdl-cell mdl-cell-6-col mdl-textfield mdl-js-textfield">
<input class="mdl-textfield__input" type="text" id="screenname" pattern="[a-zA-Z0-9]{3,}" ng-model="comment.screenname" required/>
<label class="mdl-textfield__label" for="screenname">Screen Name</label>
</div>
On load, you should see all the input fields had a red line under them which indicate they are in the invalid state. And the line turns to blue once validated.
Note: The style on the check button does not work...should not be a concern in the problem.
Angular is going to check the form the same way at any point (load or later) and render the result. If you don't want to display the results on load, add logic to check whether the form has been interacted with. You can hide your error messages using ng-if="yourFormName.$dirty", or display according to the status of an individual field with yourFormName.yourFieldName.$dirty.
Click here for live demo.
What is currently implemented (wrong IMHO) is that MDL automatically validates input and doesn't mind "novalidate" form attribute. I had to implement check for empty input value (skip validation and remove is-invalid class) and, since angular form validation requires "novalidate" attribute, check:
if (input.form.novalidate = true) // skip validation
that way you can actually turn off mdl validation and leave everything to angular.
One more thing is actually required. You can create angular directive which validates expression and add is-invalid class if necessary:
div class="mdl-textfield" mdl-validator="form.email.$error"

ng-submit VS post form submit

in the usual javascript form submit , what happens is that when i do the post the element names and values automatically are sent in the HTTP request to the server without me having to collect each one of them .
what I have noticed in angular form submits is that is not the case . based on ng-submit example I have to collect each ng-model i have in the view into my controller and I have to do that in the submit function I write .
My question
isnt there a way where I can collect everything from the view without having to refer to all of the ng-models in my controller ?
Why ?
there is this case where the form elements are dynamically drawn from a directive and its not very practical to refer to each when they are so many .
Any advice ?
It depends on app to app. If yours is a SPA then you have to make sure you use ng-submit and submit the form.
When you add dynamic elements to a form if you make sure you also add the ng-model accordingly then you dont have to worry about them. It will be part of the form submission.
I think what you can do is, all the form fields(even dynamic elements) can be maintained in an object e.g. formData and then add all the models into this object. Now in the submit method you can read all the form elements values (event the dynamic elements value) using formData object.
Whenever you add a dynamic element make sure it is added to formData object
E.g.
<input ng-model="formData.field1" type="text">
<input ng-model="formData.field" type="text">
Inside submit method you can get the form field vlaues using $.param($scope.formData)

Angularjs dropdownlist and form validation

I have a page with several dropdown lists and some of them may have default entries that are not valid. It's essentially the same problem that was described here:
AngularJs doesn't validate a invalid dropdown selection
However, I think there has to be a reasonable way to accomplish this without having to check everything manually in the controller. I'd like to be able to do something like this:
<select ng-model="thisEntry" ng-options="option for option in goodOptions"></select>
<span class="error" ng-show="goodOptions.indexOf(thisEntry) == -1">Please select a valid entry from the list</span>
that also sets the form invalid so the user can't submit until it's fixed . The code above actually displays the message, but I don't know how to set the form invalid at the same time, or even in an equivalent line of code. This seems like the equivalent of a blank entry on a form that's easily handled without having to resort to javascript code.

Resources