Using a <form> element in a Windows Store app is allowable, but has a few caveats to be aware of. The most important part to understand is that generally speaking, <form> really isn’t a necessary construct in an app. On a website, <form> is often used to collect information within a group of other controls (children of the <form>). So far so good. The tricky part is what happens with the contents of those controls when some kind of button is clicked or tapped, where the behavior is specifically defined by the method and action attributes of <form>.

The method attribute, either “get” or “post,” defines the HTTP method used to interact with whatever URI is given in the action attribute. On the web, if you want to take the contents of the form’s controls and post them to another URI–presumably to store that info in a database or such–you’d use method=”post” with that URI. In this case the form contents are transmitted within the body of the HTTP request. With method=”get”, the contents of those controls are appended to the action URI as name-value pairs, such that the URI can do whatever it wants with that data.

The main caveat, then, for Store apps is that typical form submission implies navigation to a new URI, meaning that you lose your script context. If this is what you want to do, that’s perfectly fine, but typically you want to stay in the same page context as apps normally do.

The navigation behavior can be hidden if the <form> element has no explicit action, for instance:

<form method=”post”>
<input type=”text” name=”login_username” />
<input type=”password” name=”login_password” />
<input type=”submit” id=”login_submit” name=”login_submit” />
</form>

In this case, action defaults to the same URI as the current page (a web page can post form data to itself, as when doing validation). As a result, using this kind of markup in an app will cause you to lose the script context. What could happen with the above code, then, is that if you’d assigned a handler for the login_submit button’s click event in the app’s activated handler, it would work the first time but not the second time. That is, the URI navigation that happens with a submit button like this doesn’t restart the app, so the activated handler isn’t called again, even though the HTML and JavaScript for that page is reloaded.

Let me be clear on this point. When you start a Store app written in JavaScript, what gets launched is an instance of wwahost.exe that will load up whatever HTML page you identify in the app’s manifest as the start page. This, as always, means it will load and execute whatever JavaScript exists in that page (directly or via <script>). The code in such a page typically subscribes to the app’s activated event (Windows.UI.WebUI.WebUIApplication.onactivated, for which many apps use the WinJS.Application.onactivated wrapper). And this is exactly what happens if the page is reloaded through a <form> submit.

However, even though the code in the reloaded page listens for the activated event, it won’t be fired again because the app is already running. That is, the activated event is fired from within WinRT only when the app is launched or activated from some other system event (like various contracts), An internal URI navigation within an app does not “activate” the app and therefore the event is not fired.

So if the activated code for the app wired up a click handler for the submit button, it will work only the first time and not after the page is reloaded.

A second issue is that even if you did reload the page properly, an app doesn’t have access to the HTTP request body, so the form data is loast anyway.

In the code above, you can just remove the <form> element completely, then in the submit button’s click handler just extract the data you need and act on it–typically using WinJS page controls to “navigate” via DOM replacement.

Alternately, if you use type=”button” instead of type=”submit” then you remove the reposting behavior of <form> and can handle the button click in the same way. That is, a button in this case doesn’t trigger the form’s navigation behavior, so the page won’t be reloaded.

The bottom line is really that <form> isn’t particularly useful in an app (the local context, anyway), so you need to disable it’s navigation behavior one way or another. If you want to use the element for semantic markup purposes to delineate a group of input controls, that’s fine–just use type=”button” for the submit, or just use a <button> to begin with. Otherwise you can use a <div> to group the controls.

 


Comments are closed