Appcelerator Blog

The Leading Resource for All Things Mobile

Forging Titanium Episode 10: Forms

0 Flares 0 Flares ×
Editor’s note: This and future episodes of Forging Titanium are available here. Developer’s note: Titanium SDK version 1.7.3 is necessary to run this code on Android, which is available here. The most common way for users to enter data into a web application is via forms. Well, as mobile developers we want the same familiarity for our users, along with ease of configuration on our end. With the multitude of native UI components available to Titanium developers, sometimes creating this seemingly simple interface can be a more intimidating task than expected. In this episode of Forging Titanium we’ll look at how we can use CommonJS patterns to develop a simplified interface for creating cross platform mobile forms. We’ll carefully abstract the underlying functionality of forms and expose only the critical functions and properties necessary to process them via a CommonJS module. Episode Resources:
0 Flares Twitter 0 Facebook 0 Google+ 0 LinkedIn 0 Email -- 0 Flares ×

31 Comments

  1. Burel

    For Android, seems tiapp.xml needs …

    true

  2. @Burel: We seem to have lost your XML tags in your comment, but I think I know what you may referencing. Titanium 1.7.2 has a bug when using CommonJS requires with Android. You can do one of 2 things:

    1) Use Titanium version 1.7.3, which fixes this bug.
    2) Use what I think was your workaround, which is not compiling the JS when deployed. You can do so by adding this to your tiapp.xml

    <android xmlns:android=”http://schemas.android.com/apk/res/android”>
    <property name=”ti.android.compilejs” type=”bool”>false</property>
    </android>

  3. Jeff Haynie

    Great video and awesome module!

  4. I get the following Runtime error in Android:-

    Wrapped java.lang.ClassCastException: java.lang.String (file:…….app.js#3)

    This is with the latest 1.7.3 build 1.7.3.v20111013094213 and 1.8.0.v20111010000614.

    I also tried putting the stuff in tiapp.xml that Tony mentions but same problem. I have noticed several problems in general being commented upon using CommonJS with Android.

    • Kevin Whinnery

      If you can put the full stack in a pastie, create a Q&A item, and send it to us at community@appcelerator we’d be happy to take a look – the common JS standard is critical for us going forward and if there are issues, we want to address them right away.

  5. @Kevin
    How do I get the full stack? I am compiling the Android version from the Terminal in Studio. PS. I do that as Fastdev never works for me so I choose to not use it, as it is faster and more reliable to not use it. There is a bad bug in Studio which does not turn off Fastdev, even if you set it to false in tiapp.xml.

  6. @Simon: If you can’t see the full stack in Studio, you can always use ddms, attach it to your emulator/device, and grab the full stack from there.

  7. Burel

    tiapp.xml needs ‘true’

  8. Burel

    tiapp.xml —> property name=”ti.android.compilejs” type=”bool” true

  9. @Burel – changing ti.android.compilejs doesn’t make any difference.

    @Tony and @Kevin – posted problem with ddms output to Q&A

    Note rewriting example as inline factory methods works fine so seems a problem with commonJS.

  10. Great article & video. Thanks for posting.

  11. ads

    Great module Tony !
    One question :
    I have to update the content of a picker when the scrollview is already displayed.
    For this I do :
    myView.fieldRefs[“contact”].data = myContactArray;
    but when the picker is displayed it doesn’t take it in account.
    Any idea ?
    Thanks

  12. @ads: Glad you like the module. Unfortunately, though, I don’t think you can change the rows of a picker while it is open.

  13. ads

    @Tony: Ok, will see if I can tweak it myself, the problem is that I have two pickers that work in Master/detail, the first one is the customer list, and the second one is the contact list of the selected customer. So when I select a customer in the first picker, I have to change the data of the 2nd picker, so when it will show, it displays the right contact list.
    Regards

  14. Outstanding module. This will make form use so much easier to implement…once I get it working. :-) I’m running into a problem with the display’s auto dimensions both being set to 0 so the form doesn’t appear.

    My form is getting created within a UI factory because it’s used in several windows:

    Client.ui.createSiteAccessView = function( props ) {
    props = props || {};

    var forms = require( ‘/lib/forms’ );
    var fields = [
    { title: ‘Search’, type: ‘text’, id: ‘search’ },
    { title: ‘Submit’, type: ‘submit’, id: ‘registerUser’ },
    ];
    var form = forms.createForm({
    style: forms.STYLE_LABEL,
    fields: fields,
    });

    Ti.API.debug( form.fieldRefs );

    form.addEventListener( ‘registerUser’, function( e ) {
    Ti.API.debug( e );
    });

    return form;
    };

    So far, it’s just a simple search form, so the output from my debug print of the form content looks like this (along with the 0 height/width warning):

    [DEBUG] {
    name = “[object TiUITextField]”;
    }

    [WARN] [object TiUIScrollView] has an auto width value of 0, meaning this view may not be visible.

    [WARN] [object TiUIScrollView] has an auto width value of 0, meaning this view may not be visible.

    Any thoughts would be much appreciated.

  15. @Rob: Did you set the default textfield properties in the forms.js code, like I did here:

    var textFieldDefaults = {
    height: ’40dp’,
    width: ‘250dp’,
    top: ’10dp’,
    color: ‘#222’,
    borderStyle:Titanium.UI.INPUT_BORDERSTYLE_ROUNDED
    };

    If you want the dimensions to be more fluid, and not static, try using the `left` and `right` properties of the textfield to specify constraints for its width.

  16. @Tony —

    I did. Actually, to be more accurately, I did not…you did. :-) I pulled the module code from your Github repository and dropped it in my Resources/lib directory. I then copied the relevant code from your app.js into my createSiteAccessView() function to use as a starting point.

    The idea was to get something known to work into the app and then customize from there. Maybe I missed something in the copy? I don’t see anything obvious, but I’m too new to this to think it’s unlikely.

    I’m using the 1.7.5 SDK. Thanks for the quick reply.

  17. @Rob: Will be tricky to troubleshoot without your full source, but in the meantime, run the forms demo without any of your code and see if you get it working. I just built from the github repo and tested against 1.7.5 on both ios and android and it appears to work fine. You may need to find the difference between my app.js and your own to figure out what the issue is.

    Also, even when the demo runs correctly, the warning about auto width still pops up. This will pop up on scrollviews with auto widths just to let the developer know that they need to make sure they put something in the scrollview to make it appear.

  18. Okay. I’ve never noticed it except when nothing appears, but that’s also the only time I’m looking for it, so I suppose there’s a natural correlation. I’ll see if I can track down whatever delta there might be between my code and yours.

    Thanks again.

  19. I also just realized that Titanium is reporting the iPhone simulator I’m testing with (retina) as x86_64, so whatever’s going on there may be playing a role.

  20. Hi Tony Lukasavage,

    This Mahesh.I am using ur form for one of my project.My requirement is go get the values from form and display on the phone. As i see when i try to display The Titanium.UI.PICKER_TYPE_PLAIN value (for example Alaska) is not displaying.Its value is displaying as undefined when we use Alert(e.values) in android SDK. and i saw ur video closely in that also when u alert the values only the Titanium.UI.PICKER_TYPE_PLAIN values is undefined. Can u help on this. This would be greatly appreciated

    Thank you
    Mahesh

  21. Rich

    Great info thanks a ton!

    Question: How would I add an event to on of many text fields or pickers. I get the submit button you have a specific test for the button and event registerUser. I can make a click event for the entire form, but can’t get it specific to one text field or picker.

    Thanks again!

  22. Craig Myles

    Hi Rich, you should be able to access the textFields externally, as they have already been added to the ‘fieldRefs’ object. If you gave your field the id of say ‘username’ then you should be able to add an event listener by: form.fieldRefs.username.addEventListener(…

  23. Craig Myles

    If you want a data dictionary object that contains only the values of the TextFields then add something like this:

    exports.createForm = function(o) {

    var form = Ti.UI.createScrollView({

    fieldValues: fieldValues,

    });

    }

    var fieldValues = function(){
    var form = this;
    var fields = {};

    for(var i in form.fieldRefs){
    var field = form.fieldRefs[i];
    fields[field.id] = field.value;
    }

    return fields;
    }

    Then externally you could do:

    var values = form.fieldValues();
    username = values.username;

  24. Rafal

    Hi Tony Lukasavage,
    This Mahesh.I am using ur form for one of my project.My requirement is go get the values from form and display on the phone. As i see when i try to display The Titanium.UI.PICKER_TYPE_PLAIN value (for example Alaska) is not displaying.Its value is displaying as undefined when we use Alert(e.values) in android SDK. and i saw ur video closely in that also when u alert the values only the Titanium.UI.PICKER_TYPE_PLAIN values is undefined. Can u help on this. This would be greatly appreciated
    Thank you
    Mahesh

    Hi this is the same thing I see on your video and the picker just does not display a value in android… any hints…. straight code from github.

    Thank you!
    Rafal

  25. Rafal

    I figured it out change the eventkistner in forms.js to:

    button.addEventListener(‘click’, function(e) {
    var values = {};
    for (var i in fieldRefs) {
    // added by me
    if (fieldRefs[i].hasOwnProperty(‘type’)) {
    values[i] = fieldRefs[i].getSelectedRow(0);
    }
    else {
    values[i] = fieldRefs[i].value;
    }
    // added by me **
    }
    form.fireEvent(id, {values:values});
    });

    this will actually work on Android not sure if this breaks Iphone or not, no way to check.

    Good luck!

  26. Craig Myles

    Hi Tony, I’ve added a form to a modal window and it looks like the semiModalPicker won’t show now (I think Titanium prevents you from opening a window when in modal mode) – have you had this problem and what would you suggest? Cheers

  27. Craig Myles

    It’s ok, I converted it to a view and I now add it to the current window if it’s a modal, and open it as normal if it’s not

  28. Hey! I found this tutorial quite interesting.

    Does anyone know if there’s a tutorial or some document to complete this tutorial and actually send the info via e-mail?

    My best regards!

  29. Mike Pinch

    A nice and easy addition to improve this a bit is by adding

    textFieldDefaults.value = field.value || ”;

    into the forms.js addfield function. This allows you to define a default value for the field (in the demo in app.js), in case you want to have some persistence on a form you are using!

    Great video!

  30. Deepti N

    i tried running the application from github in my appcelerator and found that the datepicker and state values are returning null.

    {birthday=null, zip=999, phone=557888, address=dasf, email=fdadasf@dd.com, name=dsds, state=null, password=dasf, city=dafsadsf}.

    Why are the state and birthday values are null?

Comments are closed.

Sign up for updates!

Become a mobile leader. Take the first step to scale mobile innovation throughout your enterprise.
Get in touch
computer and tablet showing Appcelerator software
Start free, grow from there.
0 Flares Twitter 0 Facebook 0 Google+ 0 LinkedIn 0 Email -- 0 Flares ×