Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A way to render a separate field #94

Open
IlyaSemenov opened this issue Feb 26, 2014 · 21 comments
Open

A way to render a separate field #94

IlyaSemenov opened this issue Feb 26, 2014 · 21 comments

Comments

@IlyaSemenov
Copy link

In many cases it is easier to render the form manually in the template file. Consider a simple form:

var form = forms.create({
    q: forms.fields.string()
});
form.handle(req, {
    other: function (boundForm) {
        ...

I want to render that field in my template in a custom hand-crafted layout. Supposedly, form.fields.q.toHTML() and boundForm.fields.q.toHTML() should render the input field only (with the pre-filled submitted value in latter case), but instead they render the entire line with unwanted extra tags:

<div class="field"><label for="id_q">Q</label><input type="text" name="q" id="id_q" /></div>

You can take a look on the degree of freedom in Django forms engine:
https://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template

@ljharb
Copy link
Collaborator

ljharb commented Feb 26, 2014

"degree of freedom" can also mean "degree of complexity" :-)

In your example, the label should never be unwanted (every input should always have a visible text label), although I agree you may not want the div.field wrapper.

If you want custom HTML for a widget, whether it be from a string in JS or from a template, you should make your own widget with its own toHTML function, that defers to an existing one if you like, and use that.

@ljharb ljharb closed this as completed Feb 26, 2014
@IlyaSemenov
Copy link
Author

In your example, the label should never be unwanted

This is so obviously not true. Consider this very Github page. Neither the top search input nor the comments textarea have any labels. Take Google front page, there is no label!

You seem to misunderstand the concept. I do not want a custom widget. Custom widgets are primarily needed for repetitive use for fields that have some specific format. Typical examples could be a color picker widget, or a date/time widget. See, that's not the first forms library I'm working with. I've been there for a long time, in many languages, starting from Perl 10+ years ago :)

What I am talking about is the ability to render input fields only, one time per each field, because the surrounding layout (other than the tag itself) is hand crafted in the main template file. That's a must in any complex web project. Please reconsider closing this ticket.

@Clijsters
Copy link

What I am talking about is the ability to render input fields only

I see it like Ilya.
I miss such opportunities very often in some frameworks. It would be nice to have something like a bool for disabling the extra stuff "done".

@ljharb
Copy link
Collaborator

ljharb commented Feb 26, 2014

I consider it a serious UX flaw, even here on github, when there is an input without an associated visible separate label.

That said, you're just looking for the input tag, so I'll reopen this and think about what makes the most sense.

@IlyaSemenov
Copy link
Author

Thanks! I agree that generally speaking there should never be an input field without a label, it's a bad UX practice indeed. The thing is, in real life a label is not necessarily a label tag. It can be an image, it can be a tab name plus placeholder (like in Github comments section), and many other ways to actually express the label.

So speaking about the forms library, it's not really correct to couple the input tag (widget) with its label. Of course, there should be a simple way to render a widget along with its label (for simple forms, like it works now), but from the architectural point of view, these better be separate decoupled concepts. May be a concept of "labeling widget" which knows nothing about what the inner widget is, with this default implementation:

<div class="field"><label for="id_q">Q</label>{{ widget }}</div>

@ljharb
Copy link
Collaborator

ljharb commented Feb 26, 2014

For semantic and accessibility purposes, there should always be a <label> tag. What it contains is indeed up to you, but the tag name should be label.

@mikeymike
Copy link

Relating to this is there a way to (on a single field) render the label after the input field? (specifically a checkbox in my case)

In a previous form system i have used it would have a renderElement and renderLabel or just plain render which would do as you'd expect. It gave a lot of flexibility and when rendering the whole form such as form.renderHTML it used by default the render function

@ljharb
Copy link
Collaborator

ljharb commented Mar 1, 2014

@mikeymike a checkbox should always be rendered inside its label for accessibility purposes - that won't ever become an option.

@mikeymike
Copy link

@ljharb I'd have to disagree there, thats why there are for attributes http://webaim.org/techniques/forms/controls#checkbox

Also my checkbox using form.toHTML() renders the checkbox and label completely separate, with the label first although I would prefer it after the input field like the ones in the webaim example above.

@ljharb
Copy link
Collaborator

ljharb commented Mar 1, 2014

for attributes should always be used, yes. I'm suggesting that for checkboxes (and radio buttons) only (not other input types), the label should always contain the input.

I haven't yet fixed that in this module yet, but I will :-)

@mikeymike
Copy link

Theres nothing wrong with having labels and checkbox inputs separate, all wrapping will do is bridge the tiny gap between the two and make that area clickable. I'm not against doing this at all, but I do agree with @IlyaSemenov that there should be more flexibility in what we can output to the page.

Is the aim of the form system to also control how I display it ?

@ljharb
Copy link
Collaborator

ljharb commented Mar 12, 2014

This is already possible if you do something like this:
form.toHTML('form_name', iterator) where iterator is a function with the signature (name, field, options) - inside that function, return field.widget.toHTML(name, field);

This won't have error HTML, or labels, or wrapper divs.

If you have a handle on a specific field, you can call its toHTML method similarly.

Does that solve your use case?

@IlyaSemenov
Copy link
Author

@ljharb, let me put it this way: if rendering a naked input field widget is to be treated as a rare edge case (as you seem to believe), indeed there is already a (rather twisted) way to achieve it.

My point is that rendering a naked input widget should be the default behaviour of boundField.toHTML() (instead of forms.render.div), or at least have a sane-looking built-in shortcut. What you suggest — repetitive use of boundField.toHTML(null, function(name, field, options) { return field.widget.toHTML(name, field) }) for every field — is beyond of being acceptable for such a frequent use case as creating a form with custom layout.

Of course, this only relates to individual fields, not the form as a whole. How form.toHTML() currently works is just fine so not sure why you were giving it as example. form.toHTML() is basically a prototyping/repetitive use shortcut anyway, in real life projects there's little chance that the actual forms don't get customized in this way or another.

If you as a library maintainer do not see any sense in this, then yes, please simply consider my case solved.

@ljharb
Copy link
Collaborator

ljharb commented Mar 12, 2014

The intended use case is indeed to call form.toHTML - at least originally, you're not supposed to be calling toHTML on individual elements.

I'm not saying forms won't support this use case - I'm trying to understand the use case, and think about how it could be achieved in a simple way without breaking the original, working use case of the module.

Can you propose an API to do this? I'm open to suggestions.

@danielst-vccp
Copy link

Has there been any advancement on this? I find myself needing to output a single form into logical sub sections. toHTML on individual fields doesn't seem to maintain context of things like errors etc?

@ljharb
Copy link
Collaborator

ljharb commented May 27, 2015

Can you elaborate on the use case? Specifically, why you find you need to do that?

@IlyaSemenov
Copy link
Author

Let's say I want to create Google2, which looks like Google but also validates the search string (yay!). Currently there is no simple way to do that because the forms library emits a lot of extra tags that Google doesn't have.
screen shot 2015-05-27 at 23 30 23

Or, let's say I want to create a new, better StackOverflow, and I started with the Sign up form: https://stackoverflow.com/users/signup (only without the javascript validation). Not possible either!
screen shot 2015-05-27 at 23 42 15

I am pretty sure that if I take top 10 modern sites, I wouldn't be able to process forms in any of them with your forms library. But that's what we do, don't we? We create sites that work and sell. Does that qualify as a use case?

@ljharb
Copy link
Collaborator

ljharb commented May 27, 2015

I'm not sure I understand why that wouldn't be possible. You'd certainly need to overwrite toHTML on the widgets that you wanted to customize, but you can produce any form with forms, just not necessarily as configured out of the box.

@IlyaSemenov
Copy link
Author

Technically that's correct, and I was a little exaggerating.

But if there were a method that simply emits a naked input (a shortcut for boundField.toHTML(null, function(name, field, options) { return field.widget.toHTML(name, field) })), that would be suited for any of those top 10 sites out of the box, without any need for creating "widgets", and readily available for the division of labor between the backend node.js developer and the no-so-qualified guy that does the HTML cut and puts <input>'s where they belong.

95% of the form fields in the actual web sites do not conform to what boundField.toHTML() emits, and never will. 99% of the forms do not conform to what form.toHTML() emits, and never will. Basically we have a default which is only useful for prototyping and academic use, and we are forced to jump through hoops for any real work (involving commercial-grade design and HTML cut), while there is an obvious simple method which would allow to avoid any of that work and keep the code clean, simple, readable and supportable.

@danielst-vccp
Copy link

I found what I was looking for. To try and explain, I needed control over where in the DOM individual fields appeared. I was able to use the field.toHTML() method. The issue I had is that I needed to specify the name of the field in the first argument else it wouldn't bind.

With regards what Ilya is asking for, I have to agree. You have methods on the field object for the individual label, errors etc. Why not the standalone input too?

@ljharb
Copy link
Collaborator

ljharb commented May 27, 2015

I'd be happy to review a PR that adds that - I think we can have a more productive discussion that way :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants