How to generate 'required' Attribute in GWT using UIBinder? - html

Expected HTML
<input class="sth" type="input" required/>
How to generate this using UIBinder in GWT?
I am using following and not generating the required attribute
<g:TextBox ui:field="username"/>

You cannot do it in UiBinder with standard TextBox widget. If this is a one-off situation, set it in code. If this is something that you use often, create your own widget by extending TextBox and adding:
public void setRequired(boolean isRequired) {
if (isRequired) {
getElement().setAttribute("required", "required");
}
}
Then you can use it in UiBinder:
<w:MyTextBox ui:field="username" required="true"/>
where w links to your widgets folder.

Related

How to use runat = "server" in input tag?

I'm writing in asp.net. When I add runat="server" property to my input tag, its value is null. When I remove runat="server" it works correctly. Who knows the reason?
I want change its property from code behind, that's why I wrote runat="server". However, the value is null.
protected void btnSaveChanges_Click(object sender, EventArgs e)
{
string current_id = Session["Current_user"].ToString();
string a = Request.Form["newusername"];
string b = Request.Form["newpassword"];
string c = Request.Form["rewpassword"];
}
Code for control:
<input type="text" name="newusername" placeholder="Enter Username" required="required" runat="server"/>
When you add runat="server" and make the simple HTML control to asp.net HTML control, then asp.net renders the id and the name of that control in a manner that does not conflict with other asp.net controls on the same page.
So change the input to: (note now I add id, and remove the name!)
<input type="text" id="newusername" placeholder="Enter Username" required="required" runat="server"/>
and get the value using the post like this:
Request.Form[newusername.UniqueID]
or using the value:
newusername.value
other links to consider:
Accessing control client name and not ID in ASP.NET
Use newusername.Value to access the value of the control in your server side function.
Like
protected void btnSaveChanges_Click(object sender, EventArgs e)
{
string current_id = Session["Current_user"].ToString();
string a = newusername.Value;
string b = newpassword.Value;
string c = rewpassword.Value;
}
You can't change an HTML control's properties using c# server side code. But you can do that using several other methods -
Method 1
you can use plain javascript or jquery to alter the HTML DOM element.
Method 2
you can create the HTML elements you want dynamically using HtmlGenericControl.
HtmlGenericControl username = new HtmlGenericControl("input");
username.attr("type", "text");
username.attr("name", "newusername");
And then you can append the controls into some div, like,
Front-End HTML code where you will add your dynamic controls-
<div id="dynaHtml" runat="server"></div>
Now, you can use that div to add your dynamic controls to page -
dynaHtml.Controls.Add(username);

asp.net conditionally disable a tag helper (textarea)

I want to enable or disable a textarea depending on a condition that evalueates from the model, and I am using the textarea tag helper.
In other words, something like this:
<textarea asp-for="Doc" #(Model.MustDisable ? "disabled" : "")></textarea>
But I got the following design-time error: The tag helper 'textarea' must not have C# in element's attribute declaration area.
Then I tried:
<textarea asp-for="Doc" disabled='#(Model.MustDisable ? "disabled" : "")'></textarea>
which did not show any design time error but it renders like this:
Model.MustDisable==true renders disabled='disabled' AND Model.MustDisable==false renders disabled.
So the text area will always be disabled.
Then I tried (removing the 's):
textarea asp-for="Doc" disabled=#(Model.MustDisable ? "disabled" : "")></textarea>
which did not show any design time error but it renders the same as the previous one.
How can I implement this the right way?
It is actually very simple, the disable attribute is already working as you want - you can pass in a boolean value:
<textarea asp-for="Doc" disabled="#Model.MustDisable"></textarea>
if false the disabled attribute is not rendered:
<textarea></textarea>
if true the disabled attribute is set to "disabled":
<textarea disabled="disabled"></textarea>
I was facing the same issue with select tag helper, i tried few things and it worked.
Try this-
<textarea asp-for="Doc" disabled="#(Model.MustDisable ? "disabled" : null)"></textarea>
The textarea tag helper does not have direct support to conditionally render a disabled text area. But you can always extend the TextAreaTagHelper and add this feature.
So create a new class which inherits from the TextAreaTagHelper class.
[HtmlTargetElement("textarea", Attributes = ForAttributeName)]
public class MyCustomTextArea : TextAreaTagHelper
{
private const string ForAttributeName = "asp-for";
[HtmlAttributeName("asp-is-disabled")]
public bool IsDisabled { set; get; }
public MyCustomTextArea(IHtmlGenerator generator) : base(generator)
{
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (IsDisabled)
{
output.Attributes["disabled"] = "disabled";
}
base.Process(context, output);
}
}
In your _ViewImports.cshtml file, using the #addTagHelper directive, specify the assembly where the above class is defined so that our new tag helper is available in other razor views.
#addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
#addTagHelper "*,YourAssemblyNameHere"
Now in your views, you can use it like
#model YourSomeViewModel
<textarea asp-for="Doc" asp-is-disabled="Model.MustDisable"></textarea>
where SomeViewModel has a Doc and MustDisable property.
public class YourSomeViewModel
{
public string Doc { set;get; }
public bool MustDisable { set;get; }
}
I am posting this separately since I don't have enough reputation to add a comment to Shyju's answer.
If you inherit from one of the default tag helpers and then register both the default tag helpers and your custom tag helper in _ViewImports.cshtml, then both tag helpers will be executed for the specified tags.
For the following:
[HtmlTargetElement("textarea", Attributes = ForAttributeName)]
public class MyCustomTextArea : TextAreaTagHelper
{
private const string ForAttributeName = "asp-for";
...
With the following _ViewImports.cshtml:
#addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
#addTagHelper "*,YourAssemblyNameHere"
Both MyCustomTextArea and TextAreaTagHelper will be executed for each textarea tag.
I did not notice any problems with the output generated for textareas, but I have run into problems inheriting from other default tag helpers. The solution is to remove the default tag helper in _ViewImports.cshtml.
#addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
#addTagHelper "*,YourAssemblyNameHere"
#removeTagHelper "Microsoft.AspNet.Mvc.TagHelpers.TextAreaTagHelper, Microsoft.AspNet.Mvc.TagHelpers"

Submitting a form using a custom button using HTML Web Components

I have defined a custom DOM element, but when placed inside a form, it does not submit it. How can I get the form to submit when I click the button?
<form action="/foo" method="GET">
<my-button type="submit">click me</my-button>
</form>
This is the prototype configuration for the custom element:
myButton = Object.create(HTMLButtonElement.prototype);
The template for the button looks like this:
<template>
<button type="submit" id="button"><content></content></button>
</template>
Came across this question today, but found a more modern alternative subsequently: web components can now be native form elements. There's a great read on the topic here.
The long and the short of it is you can now associate custom components with a form, meaning they're included in the form's elements property - a HTMLFormControlsCollection of all the elements controlled by the form.
To do this, you need to add the following to your component:
class MyComponent extends HTMLElement {
static get formAssociated() { return true; }
constructor() {
super();
this.internals = this.attachInternals();
}
}
this.internals will then contain everything you need to interact with the form in question, e.g. this.internals.form, this.internals.setFormValue(), this.internals.checkValidity().
For the submit button, you could, for example, use:
connectedCallback() {
const { internals: { form } } = this;
this.buttonEl.addEventListener('click', () => form.submit());
}
You are doing it wrong. Though event bubbling from shadow DOM to owner document is somehow possible, it’s tricky and in general is a wrong approach. Instead of hiding button into shadow, one should use is= attribute of button:
<form action="/foo" method="GET">
<!--my-button type="submit">click me</my-button-->
<!-- ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓ -->
<button type="submit" is="my-button">click me</button>
</form>
More info.
When your custom element extends a native element like HTMLButtonElement, you can no longer use a custom tag name like <my-button> (unfortunately). You have to use the native tag with the is= attribute:
<button type="submit" is="my-button">
If you do not extend a native element (called "type extension" in the spec), then you can use your custom tag name. Type extension example in the spec

Getting a file from html input field with vaadin

I have to use a HTML snippet to get an image from Android/iOS devices with
<input type="file" accept="image/*" capture="camera" />
which is displayed in a Label:
Label label = new Label("<input type=\"file\" accept=\"image/*\" capture=\"camera\" />");
label.setContentMode(Label.CONTENT_XHTML);
Because I'm using Vaadin on Liferay I'm not sure how to obtain the Image since there is no POST submit
How am I able to get this image?
You need to write custom Vaadin component which extends FormPanel. Thats not hard as it may sounds, just let Vaadin Widget creator generate classes for you and then replace auto-generated GWT component with the following code
public class CameraCaptureWidget extends FormPanel {
public CameraCaptureWidget() {
setEncoding(FormPanel.ENCODING_MULTIPART);
setMethod(FormPanel.METHOD_POST);
FileUpload f = new FileUpload();
this.add(f);
f.getElement().setAttribute("accept", "image/*");
f.getElement().setAttribute("capture", "camera");
f.addChangeHandler(new ChangeHandler(){
#Override
public void onChange(ChangeEvent event)
{
submit();
}
});
}
}
You can also add button instead of adding ChangeHandler on FileUpload itself.
After you are done with that you need to handle submit() event in the Connector. Example:
public CameraCaptureConnector() {
getWidget().addSubmitHandler(new SubmitHandler()
{
#Override
public void onSubmit(SubmitEvent event)
{
Window.alert("Hello world");
}
});
}
You may also need to remove some unnecessary auto-generated methods.
This solution generates this HTML code in DOM:
<input capture="camera" accept="image/*" class="gwt-FileUpload" type="file">
Should you encounter trouble, please make sure you have read https://vaadin.com/wiki/-/wiki/Main/Creating+a+simple+component

GWT uibinder autocorrect off

im using GWT uibinder method and my html contains a textbox like
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:idmw="urn:import:com.testing.wid.impl">
<g:HTMLPanel>
<table align="center" valign="center" height="25%">
<tr><td><g:TextBox ui:field='searchS' /></td></tr>
</table>
</g:HTMLPanel>
How can i TURN OFF autocorrect and autocapitalize for this Textbox??
i tried
<g:TextBox ui:field='searchS' autocapitalize="off" autocorrect="off"/>
but i get
[ERROR] Class TextBox has no appropriate setAutocorrect()
method Element <g:TextBox autocapitalize='off' autocorrect='off' ui:field='searchS'>
Any other way i can do this???
Thanks
As already pointed by #Boris Brudnoy there is no built-in way to do it with TextBox. Takin futher his suggestion it will be nice to extract this into new custom component (to simplify reuse and support):
Add new package (for example com.app.shared.customcontrol)
Add new CustomTextBox:
public class CustomTextBox extends TextBox {
public void setAutocomplete(String value){
this.getElement().setAttribute("autocomplete", value);
}
public void setAutocapitalize(String value){
this.getElement().setAttribute("autocapitalize", value);
}
}
Declare new namespace using UI binder and use your component:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:c="urn:import:com.app.shared.customcontrol">
<g:HTMLPanel ...>
<c:CustomTextBox ui:field="..." autocomplete="off" autocapitalize="off" />
</g:HTMLPanel>
</ui:UiBinder>
As alternative way if you want apply these settings system wide you can do it via constructor:
public class CustomTextBox extends TextBox {
public CustomTextBox() {
this.getElement().setAttribute("autocomplete", "off");
this.getElement().setAttribute("autocapitalize", "off");
}
....
}
What you've tried will not work since GWT doesn't translate UiBinder attributes directly into HTML element properties. Instead, as your error message hints, it looks up widget setter methods of the form set[UiBinder_attribute]. Since there is neither setAutocorrect nor setAutocapitalize method in the TextBox class, the errors you're getting are expected.
What you could do is drop to the element level and write something like this, e.g. in your widget's constructor:
public MyWidget() {
initWidget(uiBinder.createAndBindUi(this));
searchS.getElement().setProperty("autocapitalize", "off");
searchS.getElement().setProperty("autocorrect", "off");
}