custom web component form element for constraint validation - html

Only some HTMLElements support the constraint validation api (e.g., HTMLButtonElement). I want to create a custom web component, which also supports the constraint validation api.
In the following an example is given for the desired outcome:
<form>
<input name="title" required>
<custom-form-component></custom-form-component>
</form>
<script>
const form = document.querySelector('form');
form.checkValidity();
</script>
The custom-form-component could call setCustomValidity on itself (based on the respective user input context) and validate itself true or false. Thus, the call on the form.checkValidity() should return true or false with respect to the outcome of the custom-form-component.
As I found from documentaion (e.g. on MDN) only for some element it is possible to attach a shadow root. It is not possible for form elements. However, only form elements suport the constraint validation api.
concrete question:
How can I realise a custom web component, which supports constraint validation api?

This is a new introduction to Web Components. As of Sept 25, 2019 only Chrome 76 supports it.
Here is an article provided by Google Web Devs:
https://web.dev/more-capable-form-controls/
It talks about the various additions to Web Components that let them properly integrate as a form element.
This includes:
Form validation
The :disabled, :invalid and :valid CSS pseudoclasses
The formdata event
And a static formAssociated property that tells the browser to treat your element like a form control.
Plus several other things that allows your control to function correction in a <form>

Related

How can I validate on the client if I use MVC validation but posting a JSON object?

I'm developing a ASP.NET Core web application where I'm using DataAnnotations to decorate my view model with validation attributes. When I open a detail page with my inputs, I see that Core added the HTML5 validation attributes to the rendered HTML (i.e. data-val="true").
However, I wrote custom client-side code when the user clicks on the Save button like this:
$(document).on("click", "#SaveAsset", function (event) {
event.preventDefault();
Asset.Save();
});
I also have a Save function defined like this:
window.Asset.Save = function () {
var postData = {
'Id': $("#Id").val(),
'SerialNumber': $("#SerialNumber").val(),
'PartNumber': $("#PartNumber").val(),
'assetTypeId': $("#AssetTypeId").val()
};
$.post('/Asset/SaveAsset', postData);
}
I need to validate on the client side first before calling $.post but I'm confused about how to do it. Microsoft shows that the unobtrusive javascript works automatically when you use it with forms. But I'm not using the HTML form element to submit my page. So how can I trigger the HTML5 validation attributes?
I added the links to jquery.validate.js and jquery.validate.unobtrusive.js. Right now, if I click the Save button the data is sent to the server and the controller checks the ModelState. But it shouldn't even be sending anything to the server. The client should stop the validation.
Should I even stop doing it this way? For example, creating my postData JSON object by getting the val() of each input.
Should I use the form element? I stopped using it because my page has hundreds of inputs so I was worried I would have problems. This way, I have control over each input.
Use a javascript solution like jQuery Validation Plugin to validate data before sending to the server. Otherwise, send the data to the server, and return a the errors with a bad request if validation fails.
Eg.
Return BadRequest(string[]{"Name is required", "Id must me a number"});
then capture the errors and shoe to the user

Yii2 data attributes handled by the framework

So, if there is a need to place a link somewhere in some template, and want it work by post method, i just add a data-method = 'post' attribute.
If i want to send some parameters, then just add data-params-param1 = "param1Value" attribute.
If i need a confirmation before this link work - add data-confirm = "Some comfirmation message" attribute.
The question is: what other data-* attributes i can use when developing with Yii2, or where i can find information.
I have tried to google, look in Yii2 api - no results.
AFAIK there is no documentation for this at the moment. It's only mentioned in few places.
Based on the current yii.js, yii,captcha.js, and yii.gridView.js these data-* are specially handled:
form
method
params
pjax
pjax-push-state
pjax-replace-state
pjax-timeout
pjax-scrollto
pjax-push-redirect
pjax-replace-redirect
pjax-skip-outer-containers
pjax-container
yiiActiveForm
yiiSubmitFinalizePromise
yiiCaptcha
key

Django code to open sepecific tab in render_to_response in view

In my Django code I want to implement the following flow:
After submitting a Html form to view
Redirect to next tab in same HTML form which contain next form.
This is my code so far:
def addnewroute(request):
if request.method == "POST":
# do needed
render_to_response('useradd.html')
Introduction
Tabs are usually a visual (UI) element; meaning that there are CSS styles defining the actual tabs as "pressed" or "depressed". How the tabs "change" is defined by the implementation method you choose. Let's look at the simplest solutions.
Manual render (hard code / multi template)
If you prefer to build it all manually, you can add a condition to choose the correct html template, which would already be pre-styled to the correct tab pressed, and display the required content. I would not recommend this method except to learn more of how the internals work and as proof of concept.
def addnewroute(request):
# ...
if step1:
return render_to_response('useradd-tab1.html')
if step2:
return render_to_response('useradd-tab2.html')
Context / Template reuse
If you prefer to reuse most of your template content you can utilize the context dictionary argument to pass a step variable (to define in "which tab you should be now"), and a content variable (containing the tab content or other switch data), into your template; which will change depending on the reached step:
def addnewroute(request):
# ...
if step1:
return render_to_response('useradd.html', {'step': 1, 'form': form1})
if step2:
return render_to_response('useradd.html', {'step': 2, 'form': form2})
Then, use the passed context variables in your template, to define the condition that toggles the selected style on the tabs and displays the relevant form.
<div id="tab1" class="tab{% if step1 %} selected{% endif %}">...</div>
{{ form.as_table }}
This method is very similar to the first, except the same template is reused for both steps.
Caveats with above direct render implementations
The above methods can accomplish what you asked about; however, there are a few caveats. First, the URL remains the same, which means the user cannot navigate between steps in a persistent manner. Second, the amount of "wiring code" you would have to write (front and back-end) will be a real labor. This is why I would recommend one of the following implementations for a "stepped form".
Form Wizard
Django (versions >= 1.4, < 1.8) shipped with an "optional “form wizard” application that splits forms across multiple Web pages". The Django Form Wizard uses a specialzed WizardView class based view to simplify multi-step form creation. Note: As of Django 1.8, The form wizard was moved out of django.contrib into it's own package django-formtools.
Javascript
A more sophisticated solution may involve Javascript activated tabs, such as bootstrap tabs. In this case you would have to either: a. render all the forms in the same template (hidden by default, toggleable by on-click events) or b. fetch the data for the forms asynchronously. The upside of this solution is a more immediate UI feel for the user, the downside is definitely more complexity.
More help
If you are new to Django, templates, tabs, etc, I would suggest implementing the solutions above from the first to the last, to better understand how the internals work; and then, how you can DRY and simplify your code.
Please note that similar questions has been asked a few times on SO, such as here, here and here. So if you have any more trouble you can try searching for a related answer.

Specification advises to "redirect the response [of a form] to a hidden HTML iframe", how to achieve this?

The CMIS specification says this about the HTTP response to a submitted HTML form:
In general, the response is not useful for an end-user.
Therefore, clients should redirect the response to a hidden HTML iframe.
The iframe’s onLoad event can be used as an operation status notification.
("client" above means a webpage in a browser)
I don't see how it is possible, in HTML, to "redirect the response to a hidden HTML iframe".
The form can not be inside the hidden iframe, as the form needs to be visible. And if the writers had meant to hide the iframe once the form has been submitted, the wording would have been different.
I wonder why they don't recommend ajax instead, but that is not the question. I want to follow their recommendation, or prove them that their recommendation makes no sense.
Can anyone give me an example of such a form that "redirects the response" to an iframe?
Or an example of what the specification was really trying to say?
Or is it just impossible to achieve?
Ajax only works properly if the application is hosted on the CMIS repository because of the same origin policy.
The hidden frame approach works even if the application is served from a different host.
Here is an example:
<script type="text/javascript">
function createCallback() {
...
}
</script>
<form action="..." method="POST" target="createResult">
...
</form>
<iframe name="createResult" style="display:none;" onload="createCallback()"></iframe>
Here is a complete example:
https://svn.apache.org/repos/asf/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings-war/src/main/webapp/web/index.html

PUT request turns into GET?

A form in my app has the following:
<form action="/faculty/update/agxzdGFuZHJld3NqaHNyDQsSB0ZhY3VsdHkYBww" method="PUT" accept-charset="utf-8">
However, upon submission the request is treated as a GET and is handled by def get() and not def put(). Any help would be appreciated!
Edit:
Thanks for the responses. If I can't use method="PUT" what is the best way of directed the form the the put() method within my handler class? Should I add another handler within main.py?
HTML v4 and XHTML v1 only support the GET and POST request methods within HTML forms.
On the other hand the GET, POST, PUT and DELETE methods are supported via XMLHttpRequest in all modern browsers.
Related Stack Overflow post:
Are the PUT, DELETE, HEAD, etc methods available in most web browsers?
EDIT:
Further to your update, I think your only options would be:
Use the POST method in your form and handle it through the post() handler.
Use AJAX (XMLHttpRequest) to post your form with JavaScript, using the PUT method.
Use HTML5, but this will not work in Internet Explorer.
Browsers only do GET & POST methods. See if your app's platform can simulate PUT methods via a "method" parameter.
I believe GET and POST are the only valid values on a FORM method attribute.