1

I have to build a form with a huge number of fields (potentially >1000 fields). Because of the recommended GET URL length limit I want to split it into several smaller forms (of say 12 fields each) that submit when they have been completed.

Basically what I'm looking for is some kind of form.onBlur event: I want to submit a form only when:

  • one of its input loses focus (blurs)
  • none other of this form's input has focus

Any ideas on a good way to deal with this? Maybe I need to make each input.onBlur event check the current focus state of other inputs of the form?

EDIT: I am well aware of GET vs POST including security concerns and data volume. For my specific problem with my specific setup, GET requests are the only option; hence this question.

E. Villiger
  • 876
  • 10
  • 27
  • 6
    If your form is really THAT large, you should probably not be using `GET` but `POST`. There is no reason why you should be submitting using `GET` for such a large payload. – Terry Mar 01 '19 at 12:25
  • 1
    Sadly, `POST` is not an option in this case (front-end development only) – E. Villiger Mar 01 '19 at 12:26
  • and quite apart from that, a better UI would be to use a wizard-like approach where the user clicks "next" to go to the next section (if there are many sections, provide a shortcut way to jump between them, like a list of sections). Then it hides the previous section and shows the new one. Much nicer to view and easier to handle the transition between each part, and you can perform actions there (such as saving the progress). – ADyson Mar 01 '19 at 12:27
  • 4
    "Sadly, POST is not an option in this case (front-end development only)"...this makes no sense. If you're not in charge of the backend, fine, but you have to talk to the people who are and say the way they've designed it to only accept GET requests is not practical. It can even cause security breaches (e.g. if form data containing personal details or similar is in the URL's querystring it can end up in server logs etc where it might persist for years and/or be visible to people who don't need to see it. It's generally not a good idea to submit detailed data via GET.) – ADyson Mar 01 '19 at 12:27
  • 1
    @ADyson That is a very subjective point. It depends entirely on the kind of data / UI. In my case it's kind of a table layout that needs to all be visible at the same time. – E. Villiger Mar 01 '19 at 12:28
  • in any case, if you're proposing to split this into separate forms and submit the data in stages, that would also require a change to the backend (so it won't fail to validate if bits are missing, or repeatedly save partial versions of the same entity, or whatever (I'm speculating obviously but those are possible issues, depending on the precise circumstances)), so either way you have to alter the server-side – ADyson Mar 01 '19 at 12:28
  • Still, `GET` does not take you anywhere. Browsers have a limit on how long a URL can be, so with 1000 fields you will definitely hit the character limit https://www.quora.com/What-is-the-maximum-mount-of-characters-allowed-for-URLs-And-what-happens-if-you-go-beyond-the-maximum – Terry Mar 01 '19 at 12:28
  • 1
    @Terry that's exactly why I'm proposing splitting it up as outlined above, please read the question first. I agree that the backend should be accepting POST requests as well, but with the current setup (that I can't change) that's not feasible. – E. Villiger Mar 01 '19 at 12:29
  • 2
    The bottom line is, as I've outlined, you won't be able to solve this without some kind of change to the backend as well. So if a change is required, the simplest and most obvious solution is to move to using POST. You could split it up into lots of smaller GETs but that's a lot more work and requires changes both on the front and backend anyway. Exactly why are you claiming that it's impossible to use POST? If it's just that you can't request changes to the backend then that won't wash because of the reason I've just mentioned (i.e. splitting it up still requires backend changes anyway). – ADyson Mar 01 '19 at 12:35
  • 1
    I think it’s pretty pointless (and not actually correct) to keep telling OP they have to change something they cannot change. –  Mar 01 '19 at 12:37
  • 2
    The backend is a CMS with an extension. That extension has built-in support for GET variables, but not POST. There, is that clear enough for you? – E. Villiger Mar 01 '19 at 12:38
  • @D_N maybe, unless it happens, as in this case, that it will be impossible to build a working solution without changing that particular thing. We can mess with the front-end as much as we want, but in the end if the OP wants to break up the current single form submission into lots of smaller submissions, that requires a change to how the back-end deals with the requests it receives. Otherwise it will almost certainly not process the data properly. It was unclear if OP was claiming the back-end could not be modified at all, or just that POST was not allowed (which is unusual). – ADyson Mar 01 '19 at 13:16
  • @E.Villiger It's clear, thankyou. What's unclear is whether you also have the ability to change the behaviour of the extension? Because if you don't, you can go ahead and split up your front-end into several small forms, and submit each one separately. But how will the backend react when you submit the first form and it only contains 10% of the fields it's expecting? Maybe it will say the data is invalid because some mandatory fields are missing. Even if that's not an issue, what then? ... – ADyson Mar 01 '19 at 13:17
  • @E.Villiger ...I assume this backend will save a record into the database? Maybe a new one, maybe an update, you didn't say. But either way, if we save only part of the record successfully on the first submit, how will it react when you submit the second form? Right now it doesn't know it's a subset of the data, so likely it will either create another new record with the second set of data, or it will update the record, but save only the second submitted fields, and blank the rest (since they're missing from the 2nd form). So regardless of GET or POST you must change _something_ on the backend – ADyson Mar 01 '19 at 13:19
  • @ADyson, it may be as you say. But as you said above, you speculate as to common reasons it *could* fail and then determine the backend *must* change. What if this extension only stores input it actually receives and doesn’t care about completeness? Or OP can change settings without changing the extension itself, which leaves the Q intact? Or whatever? Bring up the issue, yes, but it has limits. –  Mar 01 '19 at 13:48
  • 1
    Note that giving all information about the context of your question upfront can help mitigate the need for these lengthy comment exchanges. [ask] has some guidance regarding this: "Include any ... unusual circumstances". – Heretic Monkey Mar 01 '19 at 13:49
  • @D_N Speculation perhaps, but do you know of any CRUD system which would be able to survive this change of approach without needing the backend to change? It's _extremely_ likely that this will cause problems, unless the system is unbelievably flexible about what is submitted and already programmed to deal with the potential for partial updates - again it seems highly unlikely that's the case for some random CMS extension (especially one which is so half-baked it only supports GET requests). So yeah it's my opinion, but I'm issuing a warning. Do you think my scenario is likely, or not? – ADyson Mar 01 '19 at 13:55
  • @D_N "What if this extension only stores input it actually receives and doesn’t care about completeness?" . Maybe, but we can assume that the form as originally intended to be submitted would be stored as one complete item. If you start submitting partial items then they will likely be stored separately without any link between them, so there is then no way to re-create the entire submission. Yes it's _possible_ that it works the way you've described, and can cope with this, or that there's a magic button to turn it on, but realistically that's probably not the case. – ADyson Mar 01 '19 at 13:58
  • @D_N ...so my intent is to prevent OP from wasting lots of time on a UI re-design which breaks the current contract with the backend, without checking if the backend will be compatible with the change, or could be amended as such. The implication (it being some installed extension) is that change may be difficult. I got the impression that the OP was focused on changing the front-end and avoiding the querystring limit, without having considered how this would play out when interacting with the backend. I just want them to think about it, that's all. I outlined a scenario to help that process. – ADyson Mar 01 '19 at 14:00
  • @ADyson, I think it’s fairly likely but not the point of the question. So answer the question and note the likely snag. –  Mar 01 '19 at 14:00
  • @D_N why would I spend time on writing a UI solution which probably has a 95%+ chance of failure? Better than the OP puts more constraints on the scenario first (primarily by commenting on the possibility of amending the backend, or whether it will in fact already support the desired multi-form/request structure without modification). People below this line evidently disagree but I don't really much point in providing a solution which doesn't work in its intended context. The bigger picture is always important when solutionising. – ADyson Mar 01 '19 at 14:07
  • @D_N And if it turns out that backend modification is going to be necessary, then clearly amending it to read POST variables instead of GET is probably going to be a lot simpler than supporting partial CRUD. This is bordering on an X-Y problem, in that sense. – ADyson Mar 01 '19 at 14:08
  • I'm not going to answer anymore specifics on POST vs GET, because that is not what this question is about. Providing more context would have simply been too confusing, maybe I should have just left out all of the context. The question is exactly what the title says. – E. Villiger Mar 01 '19 at 16:57
  • Ok but if you actually read my comments you'll see I wasn't asking about get Vs post any more. – ADyson Mar 03 '19 at 00:23

2 Answers2

2

Given that each form_element can be identified by a class you could do something in style with

$(".form_element").on("focusout", function(){
  let do_query = true;
  setTimeout(function(){
     $(".form_element:input").each(function(){ 
       if($(this).is(":focus")){
         do_query = false;
         return false; //Exit the each loop
       }
     });

     if(do_query){
        console.log("I'm going to perform the query");
     }

  }, 200);
});

I found that without the set timeout it would always trigger false since the new element would not have the time to GAIN its focus.

See jsfiddle here with working example

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Albin wärme
  • 251
  • 1
  • 14
  • For a non-jQuery way to detect focus: https://stackoverflow.com/a/17614883/241244. (Don’t you mean `$(this).find(':input')` or `$someVarStoringThisForm.find(':input')` to restrict to the individual form?) –  Mar 01 '19 at 13:31
  • If you were to say $(this).find(':input') here it would only target the jQuery element that just lost it's focus. Therefore the mention of $(".form_element:input") . After a given element loses it's focus he wanted to check if **all** other form_element were out of focus. – Albin wärme Mar 01 '19 at 13:41
  • Note that you can use [Stack Snippets](https://meta.stackoverflow.com/q/358992/215552) to provide a runnable example here on Stack Overflow so people don't have to go to a different site. – Heretic Monkey Mar 01 '19 at 13:45
  • I misread your solution. I thought you were selecting the form and then getting all inputs. Focusout bubbles, it seems, so you could do that. –  Mar 01 '19 at 13:52
  • 1
    Thank you, this is exactly what I was looking for! I was hoping there might be a more direct, simple way of doing it, but I may just have to go with this! – E. Villiger Mar 01 '19 at 16:58
1

As per my comment, you really should not be using GET if your form is that large. Plus, GET requests are only useful when you want to clearly preserve the state in the browser history. In your case, it actually makes way more sense to use POST instead.

That technicality aside, you might want to look at listening to the focusout event bubbling from any input elements in the form. It feels intuitive to attach a blur event, but since it does not bubble, you have to attach it to every single input element, which is expensive.

formElement.addEventListener('focusout', e => {
  formElement.submit();
});

document.getElementById('my-form').addEventListener('focusout', e => {
  console.log('focus lost');
});
input, textarea, select {
  display: block;
}
<form id="my-form">
  <input type="text" />
  
  <input type="checkbox" />
  
  <input type="radio" name="group1" value="1" />
  <input type="radio" name="group1" value="2" />
  <input type="radio" name="group1" value="3" />
  
  <select>
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
</form>
Terry
  • 63,248
  • 15
  • 96
  • 118
  • This actually doesn't answer my question. I only want to submit the form once ALL of its inputs have lost focus. This is triggered each time an input loses focus (e.g. if I select 1 and then select 2, it's triggered already) – E. Villiger Mar 01 '19 at 12:36
  • 1
    @E.Villiger What do you mean by all inputs loses focus? When you load the page first, none of the inputs are focused anyway. Perhaps what you want is to validate the form instead. – Terry Mar 01 '19 at 12:38
  • @Terry: Did you understand the proposed scenario of having multiple smaller forms? I only want a trigger for when I change from one form to another (or no form). – E. Villiger Mar 01 '19 at 12:40
  • @E.Villiger Apparently I don't, because the way the question was phrased is extremely ambiguous. If you want to submit the form stepwise (if you have a wizard form, i.e. multistep form), then simply submit the form when a user moves from one form to another (I suppose by clicking a "Next" button) of course. This feels like an XY problem to me now. – Terry Mar 01 '19 at 12:42
  • 1
    I think the only ambiguity is what is meant by “form” at certain points. OP has specified smaller forms, several per page, though. –  Mar 01 '19 at 12:46
  • 1
    @D_N It's not only that. I think it's pretty pointless moving forward until OP clarifies what kind of UX behavior he really intends. Since all form elements cannot be focused at once, you can't know when ALL inputs loses focus. Tracking individual focusout events is possible, but what value does that add? Not every focusout event indicates that the input value has changed. – Terry Mar 01 '19 at 12:48
  • 1
    I’m not going to debate your approach to a solution, but I think requiring more than the OP and the strict situation does is moving from answering the question to redesigning their whole setup. –  Mar 01 '19 at 12:52