Coder Social home page Coder Social logo

formotion's Introduction

Formotion

Build Status Readme Score FOSSA Status

Make this:

Complex data form

using this:

@form = Formotion::Form.new({
  sections: [{
    title: "Register",
    rows: [{
      title: "Email",
      key: :email,
      placeholder: "[email protected]",
      type: :email,
      auto_correction: :no,
      auto_capitalization: :none
    }, {
      title: "Password",
      key: :password,
      placeholder: "required",
      type: :string,
      secure: true
    }, {
      title: "Password",
      subtitle: "Confirmation",
      key: :confirm,
      placeholder: "required",
      type: :string,
      secure: true
    }, {
      title: "Remember?",
      key: :remember,
      type: :switch,
    }]
  }, {
    title: "Account Type",
    key: :account_type,
    select_one: true,
    rows: [{
      title: "Free",
      key: :free,
      type: :check,
    }, {
      title: "Basic",
      value: true,
      key: :basic,
      type: :check,
    }, {
      title: "Pro",
      key: :pro,
      type: :check,
    }]
  }, {
    rows: [{
      title: "Sign Up",
      type: :submit,
    }]
  }]
})

@form_controller = Formotion::FormController.alloc.initWithForm(@form)
@window.rootViewController = @form_controller

And after the user enters some data, do this:

@form.render
=> {:email=>"[email protected]", :password=>"password", 
    :confirm=>"password", :remember=>true, :account_type=>:pro}

Installation

gem install formotion

In your Rakefile:

require 'formotion'

Usage

Initialize

You can initialize a Formotion::Form using either a hash (as above) or the DSL:

form = Formotion::Form.new

form.build_section do |section|
  section.title = "Title"

  section.build_row do |row|
    row.title = "Label"
    row.subtitle = "Placeholder"
    row.type = :string
  end
end

Then attach it to a Formotion::FormController and you're ready to rock and roll:

@controller = Formotion::FormController.alloc.initWithForm(form)
self.navigationController.pushViewController(@controller, animated: true)

Data Types

See the visual list of support row types.

To add your own, check the guide to adding new row types.

Formotion::Form, Formotion::Section, and Formotion::Row all respond to a ::PROPERTIES attribute. These are settable as an attribute (ie section.title = 'title') or in the initialization hash (ie {sections: [{title: 'title', ...}]}). Check the comments in the 3 main files (form.rb, section.rb, and row.rb for details on what these do).

Setting Initial Values

Forms, particularly edit forms, have default initial values. You can supply these in the :value attribute for a given row. So, for example:

{
  title: "Email",
  key: :email,
  placeholder: "[email protected]",
  type: :email,
  auto_correction: :no,
  auto_capitalization: :none,
  value: '[email protected]'
}

Setting values for non-string types can be tricky, so you need to watch what the particular field expects. In particular, date types require the number of seconds from the beginning of the epoch as a number.

Retrieve

You have form#submit, form#on_submit, and form#render at your disposal. Here's an example:

class PeopleController < Formotion::FormController
  def viewDidLoad
    super

    self.navigationItem.rightBarButtonItem = UIBarButtonItem.alloc.initWithBarButtonSystemItem(UIBarButtonSystemItemSave, target:self, action:'submit')
  end

  def submit
    data = self.form.render

    person.name = data[:name]
    person.address = data[:address]
  end
end

Why would you use form#on_submit? In case you want to use type: :submit. Ex:

@form = Formotion::Form.new({
  sections: [{
  ...
  }, {
    rows: [{
      title: "Save",
      type: :submit
    }]
  }]
})

@form.on_submit do |form|
  # do something with form.render
end

form#submit just triggers form#on_submit.

Persistence

You can easily synchronize a Form's state to disk using the persist_as key in form properties. When your user edits the form, any changes will be immediately saved. For example:

@form = Formotion::Form.new({
  persist_as: :settings,
  sections: ...
})

This will load the form if it exists, or create it if necessary. If you use remove the persist_as key, then the form will not be loaded and any changes you make will override existing saved forms.

Your form values and state are automatically persisted across application loads, no save buttons needed.

To reset the form, call reset, which restores it to the original state.

View the Persistence Example to see it in action.

Callbacks

Row objects support the following callbacks:

row.on_tap do |row|
  p "I'm tapped!"
end

row.on_delete do |row|
  p "I'm called before the delete animation"
end

row.on_begin do |row|
  p "I'm called when my text field begins editing"
end

row.on_enter do |row|
  p "I'm called when the user taps the return key while typing in my text field"
end

Forking

Feel free to fork and submit pull requests! And if you end up using Formotion in your app, I'd love to hear about your experience.

License

FOSSA Status

Todo

  • Not very efficient right now (creates a unique reuse idenitifer for each cell)
  • Styling/overriding the form for custom UITableViewDelegate/Data Source behaviors.

formotion's People

Contributors

andyw8 avatar averethel avatar bensie avatar cbx avatar clayallsopp avatar colinta avatar ddrscott avatar dennismajor1 avatar dlongmuir avatar dougpuchalski avatar gantman avatar itsterry avatar iwarshak avatar jaimeiniesta avatar jdewind avatar julienxx avatar macfanatic avatar markrickert avatar matsu911 avatar matthewsinclair avatar mordaroso avatar otzy007 avatar rmoriz avatar smtm avatar sxross avatar tma avatar toamitkumar avatar toufique avatar vfrride avatar xizhao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

formotion's Issues

0.0.2 submit action triggers:

2012-07-01 19:20:18.067 EZ Score[78526:fb03] form.rb:106:in submit': undefined methodarity' for nil:NilClass (NoMethodError)
from form_delegate.rb:71:in tableView:didSelectRowAtIndexPath:' 2012-07-01 19:20:18.069 EZ Score[78526:fb03] *** Terminating app due to uncaught exception 'NoMethodError', reason: 'form.rb:106:insubmit': undefined method arity' for nil:NilClass (NoMethodError) from form_delegate.rb:71:intableView:didSelectRowAtIndexPath:'
'

Is it possible to trigger an event when clicking on something?

Hi,

Right now the only event I can see is on_submit. Is it possible to do something in this maner but for things such as static form elements?

Let's say I want to have an about static element that opens a modal with some text and maybe a couple of images. While I want the about link to look as it is part of the form, it needs to have a custom behavior attached to it.

Is it something formotion can handle, or is it outside of the scope of this gem?

Thanks!

How to separate formation into it's own controller?

Hi,

I'm trying to move all the formation stuff inside it's own separate controller,
but I couldn't see any examples, I'm using a UITabBarController in my app_delegate,
and the controller that it includes has an 'init' super method with additional code to set the tabBarItem.image
and the init method will be called via MyController.alloc.init

could you provide an example on how to separate the formation stuff into it's own controller?

Using viewDidLoad in Formotion::FormController subclass

The 'Retreive' section in the README shows viewDidLoad being overridden to add a Save button, but when I try this the form is blank. Calling super at the end of viewDidLoad solves the problem.

Is this a mistake in the README or am I misusing the framework?

FIELD_BUFFER is too big on iPad running iPhone app

RowType::Base FIELD_BUFFER seems to be 64 when running on an iPad in iPhone 2x mode. So maybe it is a bug in Device.iphone? and not really Formotion.

This causes the field frame to get too small to show the data.

Use of value attribute in CheckRow

I've noticed that CheckRow doesn't work like HTML forms, where there is a checked attribute and a value that gets returned when that row is checked. Any reason not to use the HTML approach? Not sure if you had a different vision for how to get the actual selected values from a row, when value seems to have to be true/false to represent checked or not.

In my case I'm using them as radio buttons, and assigning instances to fields. The selected instance is what I want returned, rather than a true/false.

Storing settings hash

Can you provide an example of how to store the settings hash so that it can be recalled and used as a template dynamically.

I have built an app that allows you to dynamically add field rows etc, but every time i try to save the hash it doesn't correctly store - perhaps it's just me being a Ruby noob.

I'd like to store the hash in a DB, or send it to a sever.

Hash + Model Example?

Formotion is awesome.

It's great that a form can be initialized via hash or DSL, but it's somewhat unclear to me how to initialize with a hash that ties into a model without a submit button.

I've looked at the examples:
EXAMPLE FormModel
Uses the DSL to tightly couple the form data to the model

EXAMPLE KitchenSink
Uses the hash, but the data does not persist: Looks intended to be submitted to a webservice.

Of course what I"m looking for is to get the hash to tie in comfortable with the model (the mix of the 2). I don't want to break standard and use a "Submit" button. Since no settings page operates like that.

From what I can tell, you can initialize initWithForm XOR initWithModel. What I truly want is to initWithForm (so I can use the hash cleanliness) and then set a model. Maybe even a model per section!? if I want to be tidy.

I can't imagine I'm the only one with this requirement. Perhaps the formable should have the ability to set? Instead of just init?
I saw the formable code essentially observes change. I could write my own, but it seems that should be part of the formotion core right?

I feel like I've got a handle on the problem, but not so much on the solution. Is the solution just something I'm missing, or is it actually missing due to the incipient nature of the project?

How to re-populate a form after submiting

Firstly thanks for formotion, it makes it really really nice and easy to knock up a form!

Apologies if this is a stupid question, but I couldn't see an examples of the kind of workflow that I'm after. Essentially I have a kind of list of things I want my user to do (its effectively an inbox)

My form is shown with the first item populated, the user then edits and submits. On submit I then want to populate my form with the second item in the list, when the user submits that I show the third ... and so on, until the list is empty.

So far I have something like below. How do re-populate the form after submit? Or should I create a new one?

Also worth noting:
(1) for the now, the form elements will always be the same
(2) In a later workflow the form elements will dynamically change, depending on the thing the task the user needs to complete

Any thoughts on how to implement for both (1) and (2)?

class FooController < Formotion::FormController
  def init
    super
    self.initWithForm(create_form)
    self
  end

  def viewDidLoad
    super

    self.form.on_submit do |data|
      #now save the user's edits..
      #but how do I re-populate the form with the next thing ...
    end

  end

  private

  def create_form
    f = Formotion::Form.new

    f.build_section do |s|
      s.build_row do |r|
        r.type = :string
        r.value = 'first thing'
        r.key = :text
      end

      s.build_row do |r|
        r.type = :submit
        r.title = 'Save'
      end
    end

    f
  end
end

Generic Button Types

It would be a nice feature to allow for generic buttons that have an associated callback with them.

Thanks for the great gem!

Problem with Formotion on subsequent load of persisted form

I'm having a problem where my app crashes with the following unhelpfull error:

*** simulator session ended with error: Error Domain=DTiPhoneSimulatorErrorDomain Code=1 "The simulated application quit." UserInfo=0x104400050 {NSLocalizedDescription=The simulated application quit., DTiPhoneSimulatorUnderlyingErrorCodeKey=-1}
rake aborted!
Command failed with status (1): [DYLD_FRAMEWORK_PATH="/Applications/Xcode.a...]

I am using Formotion with the persistence option to help me save application settings. If I delete the app from the sim completely and run rake, then everything works fine. I can work with the forms, enter data and everything is ok. I can even press the home button to go back to Springboard and then tap the app again and everything is ok. However, if I stop the sim (or just kill the app in the sim) and then restart the app, then it crashes with the above error as soon as I try to initialise the previously saved form.

I've narrowed down the core dump to the line of code where I am creating the controller via a call to alloc.init:

ApplicationSettingsController.alloc.init

The first time this is called, it works fine, but as I said, subsequent invocations cause a core dump.

The controller class itself isn't all that complex, it's just a holder for an API url and key:

class ApplicationSettingsController < Formotion::FormController
  PERSIST_AS = :application_settings
  def init
    @form = Formotion::Form.persist({
      title: "Application",
      persist_as: PERSIST_AS,
      sections: [{
        rows: [{
          title: "Server",
          type: :string,
          key: :server,
          text: MyApp::ApiHelper.api_url_base,
          placeholder: MyApp::ApiHelper.api_url_base,
          auto_correction: :no,
          auto_capitalization: :none
        }, {
          title: "API Key",
          type: :string,
          key: :api_key,
          secure: false,
          auto_correction: :no,
          auto_capitalization: :none
        }]
      }]
    })
    @form.on_submit do
      ApplicationSettingsController.set_api_url_and_key_from_saved_settings
    end
    super.initWithForm(@form)
  end 
end

I had some debug in there prior to posting this code and it was crashing at the Formotion::Form.persist line. I did an experiment and changed .persist to .new and it didn't crash (but it also didn't persist the form, so that was not really a solition).

The app's main windows are stitched together with a storyboard.

Anyone have any ideas what might be going wrong?

Regards,
M@

Formotion 1.2 Gem doesnt seem to compile

Hi,

Formotion looks interesting, I installed the gem and then required it in my rakefile as the instructions suggest.

I then tried to compile my app and got the message:

... uninitialized constant Formotion::RowType::Base (NameError)
... *** Terminating app due to uncaught exception 'NameError', reason: 'uninitialized constant Formotion::RowType::Base (NameError)

Also, on installing the gem I got the following RDOC error:

RDoc failure in lib/formotion/row/row.rb at or around line 92 column 29

Before reporting this, could you check that the file
you're documenting compiles cleanly--RDoc is not a
full Ruby parser, and gets confused easily if fed
invalid programs.

The internal error was:

ERROR: While generating documentation for formotion-1.2
... MESSAGE: Name or symbol expected (got #RubyToken::TkDSTRING:0x1042ae518)
... RDOC args: --ri --op /Library/Ruby/Gems/1.8/doc/formotion-1.2/ri lib --title formotion-1.2 Documentation --quiet

FormModel does not work with Models that use KVO

The FormModel does not work if you use add an observer on the model class, example take the Formmodel example

in file #user_controller.rb

class UsersController < UITableViewController
viewDidLoad
    super
    self.title = "Scoreboard"
    self.users.first.addObserver(self, 
                      forKeyPath:'team', 
                          options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld, 
                          context:nil)
  end
...
...
  def observeValueForKeyPath(key_path, ofObject:obj, change:change, context:context)
    NSLog("Changed #{obj.class.ancestors}") 
    if key_path == "team" and obj.respond_to?(team)
      UIAlertView.alloc.initWithTitle(obj.name, message:"team: #{obj.team}", delegate:nil, cancelButtonTitle:"OK", otherButtonTitles:nil)
    else
      super
    end
  end

end

The UsersController fails to load the user's form_properties.

Upgrade docs

Making an issue for this; things go both in repo and on the wiki.

  • How to add a new row type. So 1) what's functions get called in what order 2) best practices (overriding inputView, observing, etc)
  • Visual reference to what each RowType does and some of their sub-options (like subtitle, placeholder, etc)

Adding formotion to rakefile breaks app

Hi,

I'm trying to start using formotion in my first app, but it immediately breaks my app when adding it to my rakefile.
I have formotion 0.5.1, bubble-wrap 1.1.2, and the latest RubyMotion.

Here's my rakefile:

# -*- coding: utf-8 -*-
$:.unshift("/Library/RubyMotion/lib")
require 'motion/project'
require 'rubygems'
require 'bubble-wrap'
require 'formotion'

Motion::Project::App.setup do |app|
  # Use `rake config' to see complete project settings.
  app.name = 'CoffeeTimer'
end

And here's the errors I'm getting:

DYLD_ environment variables being ignored because main executable (/usr/bin/atos) has __RESTRICT/__restrict section

superclass mismatch for class Formotion::Form (TypeError)

Terminating app due to uncaught exception 'TypeError', reason: 'superclass mismatch for class Formotion::Form (TypeError)

*** First throw call stack:
(0xa5c022 0x3eccd6 0x1e9eb4 0x34ab 0x2d15)

I'm running Mountain Lion, if that matters.

Respond to key pressed

I'm nesting my form in the UINavigationController and have a "Done" button in the top right corner that starts out disabled. I'd like to enable it only when all of the elements in the form have been filled out.

Reload form (reloadData does nothing)

A simple form: select players (img link)

(btw: I added a select_many option, works just like select_one, but many)

The [+] button adds another player, but I can't get the list of players form to update. I have tried ctrlr.form = rebuild_form ; ctlr.view.reloadData, but it does nothing.

Changing picker value doesn't take effect in the picker itself

Form is initialized like this:

form = Formotion::Form.new({
  sections: [{
    rows: [
      {
        title: "Pick",
        key: :pick,
        type: :picker,
        items: ["Foo", "Bar"],
        value: ["Foo"],
        clear_button: :never
      }
    ]
  }]
})

Then later the value gets changed:

@form.sections[0].rows[0].value = "Bar"

This changes the text value, but when tapping it and loading the picker, "Foo" is still selected. Then you can't actually pick "Foo" again unless you go to "Bar" and then back to "Foo".

Broke in RubyMotion 1.18

Hi,

I just upgraded RM here and Formotion 0.3 is not working. Here is what I get when I try building my app:

rake aborted!
key not found: "lib/formotion/form.rb"

(See full trace by running task with --trace)

I am using Bundler to manage my dependencies, here is the file content (if you think another dependency may be screwing things up):

source "https://rubygems.org"

gem "bubble-wrap", "~> 1.1.0"
gem "formotion", "~> 0.0.3"
gem "teacup", "~> 0.0.1.pre"
gem "cocoapods", "~> 0.9.1"
gem "motion-cocoapods", "~> 1.1.0"
gem "motion-testflight", "~> 1.1"

In my Rakefile I have this (that theoretically order Bundler to load all my dependencies into the project, including formotion itself):

require "bundler"
Bundler.require

I don't know what is causing the problem. Please let me know if you figure it out. Also, don't forget to ask for more information if you need it :)

Is there any way to create a row with an imageView in it?

Hi there - I'm wondering if there is any way to easily have a small icon come up in a Formotion row? I'm trying to avoid having to build a custom table with a custom cell if I can, because the Formotion approach requires so much less code.

For example, the ability to specify a value for "#imageView.url" in the cell that the row defines would be perfect.

Is this something that Formotion can do?

I had a look in the current set of row types, and ImageRow seems to be for pulling an image from the camera of device's photo library.

Typo

module Formotion
  module RowType
    class MyNewRow < Base
      def build_cell(cell)
        blue_box = UIView.alloc.initWithFrame [[10, 10], [30, 30]]
        blux_box.backgroundColor = UIColor.blueColor
        cell.addSubview blue_box

        # return nil because no UITextField added.
        nil
      end
    end
  end
end

blux_box.backgroundColor = UIColor.blueColor should be "blue_box"

Popup Animation

I'm sure you were just trying to get a fix out to the nested form within a navigation stack within a tabbar problem as soon as possible and you probably already know this and plan on fixing it, but I just wanted to make sure...

The popup animation starts with that black bar on top and closes the gap as it animates upwards... You can only see it for maybe half a second, but it's definitely there every time. I'm sorry to be such a stickler but this repo will save me a lot of time and trouble if it can produce production usable results. Thanks for the time!

UIKeyboardTypeDecimalPad not available on iPad

When working with number fields, log shows this error:

Can't find keyplane that supports type 8 for keyboard Wildcat-Portrait-QWERTY-Pad; using 1191665175_Wildcat-Alphabetic-Keyboard_Capital-Letters

UIKeyboardTypeNumberPad works on iPad

Problem with DSL example in README

The Hash example works fine but when I try to create a form using the DSL syntax example in the README it crashes with the error below. I'm using v1.1.1.

(main)> 2012-09-29 10:30:45.553 Parse Test[4186:c07] row_cell_builder.rb:15:in `make_cell:': undefined method `cell_style' for nil:NilClass (NoMethodError)
  from row.rb:234:in `make_cell'
  from form_delegate.rb:65:in `tableView:cellForRowAtIndexPath:'
2012-09-29 10:30:45.554 Parse Test[4186:c07] *** Terminating app due to uncaught exception 'NoMethodError', reason: 'row_cell_builder.rb:15:in `make_cell:': undefined method `cell_style' for nil:NilClass (NoMethodError)
  from row.rb:234:in `make_cell'
  from form_delegate.rb:65:in `tableView:cellForRowAtIndexPath:'
'
*** First throw call stack:
(0xd17022 0x6a7cd6 0x2d2614 0xfb8a9 0x162cc54 0x162d3ce 0x1618cbd 0x16276f1 0x15d0d21 0xd18e42 0x26a2679 0x26ac579 0x26314f7 0x26333f6 0x2632ad0 0xceb99e 0xc82640 0xc4e4c6 0xc4dd84 0xc4dc9b 0x2d267d8 0x2d2688a 0x1592626 0x60750 0x5fe21 0x1)
terminate called throwing an exception*** simulator session ended with error: Error Domain=DTiPhoneSimulatorErrorDomain Code=1 "The simulated application quit." UserInfo=0x100653670 {NSLocalizedDescription=The simulated application quit., DTiPhoneSimulatorUnderlyingErrorCodeKey=-1}
rake aborted!
Command failed with status (1): [DYLD_FRAMEWORK_PATH="/Applications/Xcode.a...]

NumberRow return behavior

A Row with type NumberRow returns a String instead of a Fixnum/Float on form.render. One would expect it to be the latter when using the data from form.render, or am I missing something here?

Dismissing UIPickerView

Hi all,

I would like to dismiss the UIPickerView created by the picker row with a custom UIToolbar Done button. How do I get my hands on the @picker object in PickerRow?

Thanks,
Jon

rake spec terminates early?

The specs seems die early. No error message though.

$ rake spec

 Build ./build/iPhoneSimulator-5.1-Development
  Simulate ./build/iPhoneSimulator-5.1-Development/Formotion_spec.app
Form Persisting
  - works
  - works with subforms

I'm using Rubymotion 1.23

Hitting "Done" on keyboard tries to call an on_submit callback, even when it doesn't exist.

With the following simple form:

form = Formotion::Form.new({
  sections: [{
    title: "Foo",
    rows: [{
      title: "Bar",
      key: :bar,
      type: :string
      }]
    }]
  })

If you click into the Bar field, type something, and click Done on the keyboard, this happens:

2012-07-19 10:50:54.131 PFCS[70405:c07] form.rb:106:in `submit': undefined method `arity' for nil:NilClass (NoMethodError)
  from form_controller.rb:41:in `block in viewDidLoad'
  from string_row.rb:68:in `block in add_callbacks:'
2012-07-19 10:50:54.133 PFCS[70405:c07] *** Terminating app due to uncaught exception 'NoMethodError', reason: 'form.rb:106:in `submit': undefined method `arity' for nil:NilClass (NoMethodError)
  from form_controller.rb:41:in `block in viewDidLoad'
  from string_row.rb:68:in `block in add_callbacks:'

This can be remedied by adding a form.on_submit callback, but I would assume the Done button should just hide the keyboard and not try to submit the form if a callback is not defined?

Tests for each RowType

  • Base
  • Character
  • CheckRow
  • ControlRow
  • DateRow
  • EmailRow
  • ImageRow
  • NumberRow
  • PhoneRow
  • SliderRow
  • StaticRow
  • StringRow
  • SubmitRow
  • SwitchRow
  • TextRow

On Change event.

Hello,

Is there a way to change some part of the form when the makes a selection on another part ?

For example if I have a picker A with a list of universities and another picker B with a list of courses or careers I'd like to change the content of picker B according to which courses or careers ara available at the selected university on picker A.

Loving Formotion, thanks a lot!

uninitialized constant Formotion::RowType::Base (NameError)

I can't get any of the examples in formotion 1.1.5 to work.

When running FormModel, 'rake simulator', i get the message

"uninitialized constant BubbleWrap
/Library/Ruby/Gems/1.8/gems/bubble-wrap-1.1.4/lib/bubble-wrap/loader.rb:7
/Library/Ruby/Gems/1.8/gems/bubble-wrap-1.1.4/lib/bubble-wrap/core.rb:1
../../lib/formotion.rb:2"

so then I added 'require "bubble-wrap"' to the Rakefile and ran 'rake simulator' again, and this time all the files compile but when It runs I get the error message :

(main)> 2012-11-13 00:06:05.911 FormModel[4879:f803] uninitialized constant Formotion::RowType::Base (NameError)
2012-11-13 00:06:05.915 FormModel[4879:f803] *** Terminating app due to uncaught exception 'NameError', reason: 'uninitialized constant Formotion::RowType::Base (NameError)

I do have the latest versions of bubble-wrap (1.1.4) and formotion (1.1.5) installed. Im running ruby 1.8.7.

Any Idea what the issue is?

Thanks
Chris

Persist sample

Hi Clay,

I was trying to fix an issue for one of RubyMotions's user, he is using Formotion.

I launched the Persistence example and when taping on render several times, the app crashes, do you have the same behavior ?

Persistence joffreyjaffeux$ rake
     Build ./build/iPhoneSimulator-6.1-Development
  Simulate ./build/iPhoneSimulator-6.1-Development/Persistence.app
(main)> "server_url_str hello_worlddqsdqsdsqd"
"server_api_key 123123secretdqqsd"
2013-02-22 14:37:22.040 Persistence[4707:c07] Unable to set url from saved config in app_delegate: hello_worlddqsdqsdsqd
(main)> "server_url_str hello_worlddqsdqsdsqd"
"server_api_key 123123secretdqqsd"
2013-02-22 14:37:27.179 Persistence[4707:c07] Unable to set url from saved config in app_delegate: hello_worlddqsdqsdsqd
(main)> "server_url_str hello_worlddqsdqsdsqd"
"server_api_key 123123secretdqqsd"
2013-02-22 14:37:27.426 Persistence[4707:c07] Unable to set url from saved config in app_delegate: hello_worlddqsdqsdsqd
(main)> "server_url_str hello_worlddqsdqsdsqd"
"server_api_key 123123secretdqqsd"
2013-02-22 14:37:27.611 Persistence[4707:c07] Unable to set url from saved config in app_delegate: hello_worlddqsdqsdsqd
((null))> rake aborted!

Read-only forms

I want to use Formotion for what may be considered somewhat non-typical use โ€“ I only want to display data, not to edit it.

I find Formotion's DSL really nice for building up a UITableView with grouped sections. The tableview that I want to build would have several entries, each of which push another viewController, which could be achieved with multiple submit buttons.

There are really only two additional features that I would need to implement this:

  • Provide an option to make fields read-only
  • Determine which cell was used for the 'submit' action, e.g. by including the submit button's key in the #render hash

I believe I could implement both of these features, but I'm wondering whether they would fit into your vision of what Formotion should provide?

Show form in modal error'ing undefined method `sections' for nil:NilClass

I'm sure I'm doing something wrong, but I'm trying to display a form in a SettingsController that I show as a modal. However when I trigger the modal in the action inside of another controller, I get the following error:

form_controller.rb:40:in 'viewDidLoad': undefined method 'sections' for nil:NilClass

Here's the code for the 'settings' action inside of ProfilesController, which triggers the SettingsController modal:

def settings
  controller = SettingsController.alloc.initWithNibName(nil, bundle:nil)
  controller.profile = @data
  controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal
  self.presentViewController(
    UINavigationController.alloc.initWithRootViewController(controller),
    animated:true,
    completion: lambda {}
  )
end

And my SettingsController, which follows the Login example:

class SettingsController < Formotion::FormController
  attr_accessor :profile

  def init
    form = Formotion::Form.new({
      title: "Settings",
      sections: [{
        rows: [{
          title: "User Name",
          type: :string,
          placeholder: "name",
          key: :user
        }, {
          title: "Password",
          type: :string,
          placeholder: "password",
          key: :password,
          secure: true
        }]
      }, {
        rows: [{
          title: "Login",
          type: :submit,
        }]
      }]
    })

    super.initWithForm(form)
  end

  def viewWillAppear(s)
    super

    save_button = UIBarButtonItem.alloc.initWithTitle("Save", style: UIBarButtonItemStyleBordered, target:self, action:'save')
    self.navigationItem.rightBarButtonItem = save_button

    cancel_button = UIBarButtonItem.alloc.initWithTitle("Cancel", style: UIBarButtonItemStyleBordered, target:self, action:'cancel')
    self.navigationItem.leftBarButtonItem = cancel_button
  end
end

If I make form an instance variable I get the same error.

Is it possible to know which submit button was tapped if there is >1 submit button in a form?

I want to provide a simple 1-tap way for a user to select from a list of items.

If I create a Formotion form with a list of submit buttons, it's very easy for me to capture the tap and move to my next panel, but it's not obvious to me how I can work out which submit button was tapped.

Is this possible in Formation?

As background, the reason I want to do this is because I want it to be a single tap process for the user. If I use a selector, there's a tap to fire up the selector, and then a second tap to pick an item from the list. For expediency, I'd prefer to just present the list of items and allow the user to jump to the next screen with a single tap.

Alternatively, if I am off track here, is there another way to provide a single tap way for a user to select an item from a Formotion list?

Cross posted on the RubyMotion list here: https://groups.google.com/forum/?fromgroups=#!topic/rubymotion/wfNztAVy0Yk

Version 0.5 Milestone

We should start prepping for a new milestone that includes all the refactoring + row types. 0.5 is pretty arbitrary, but it looks more final than 0.0.4

Some ideas that come to mind:

  • Decide what row types to include. Everything now looks good, are there any new things we want to add?
  • Figure out how to support BubbleWrap's bleeding edge features (camera, etc) within the gem requirements
  • Included documentation in the repo about how to add new row types. The wiki gives a really nice visual format, but its good to have that data offline in the repo too (I like how BubbleWrap does this ex https://github.com/rubymotion/BubbleWrap/blob/master/HACKING.md)
  • More examples than just KitchenSink. I had a neat idea about replicating Settings.app. Maybe something more interactive to show how Formotion can be part of your app's flow.

@mordaroso any other thoughts?

How to test a Formotion Controller?

I have a simple controller shown below for which I want to write a simple set of specs that check that changing any form values and clicking save is reflected on the underlying model (using MotionModel).

What I discovered so far:

  • Can use controller context for testing for this particular case (probably because of the way I'm create the controller, see #self.create below
  • I find myself needing to add "unless RUBYMOTION_ENV == 'test'" around code in viewDidLoad type methods to avoid exceptions dealing with the differences between testing mode and a normally running app
  • In my test I can get to the row of interest by using the #row_for_index_path as in: row = @form.row_for_index_path(NSIndexPath.indexPathForRow(0, inSection: 0))

The question is how do I programmatically change the value of the UITextField associated with a row, and how do I simulate a tap the save button since I have to skip the code that adds it (my current workaround is to trigger the @controller.save method)

Then I was planning to retrieve the model using a MotionModel finder and check that the value change was reflected there. I can I will have to wrap the navigation back to the main table in another "unless RUBYMOTION_ENV == 'test'" to prevent transition since the testing environment doesn't seem to deal with multi-controller scenarios.

Thanks. By the way, wickedly awesome framework, great work @clayallsopp !

class TodoController < Formotion::FormController
  attr_accessor :todo

  def self.create(todo)
    @form = Formotion::Form.new(todo.to_formotion('Edit your ToDo'))
    controller = self.alloc.initWithForm(@form)
    controller.todo = todo
    controller
  end

  def viewDidLoad
    unless RUBYMOTION_ENV == 'test'
      super
      self.navigationItem.rightBarButtonItem = UIBarButtonItem.alloc.initWithBarButtonSystemItem(UIBarButtonSystemItemSave, target:self, action:'save')
    end
  end

  def save
    data = @form.render
    @todo.from_formotion!(data)
    @todo.save

    app = UIApplication.sharedApplication
    delegate = app.delegate
    controller = delegate.instance_variable_get("@todos_controller")
    view = controller.instance_variable_get("@table")
    view.setNeedsDisplay

    self.navigationController.popToRootViewControllerAnimated(true)
  end
end

My broken test attempt:

describe "TodoController" do

  before do
    @now = NSDate.new
    @todo = Todo.create :name => "Buy Milk",
                        :description => "We need some Milk",
                        :due_date => @now
    @controller = TodoController.create(@todo)
    @form = @controller.instance_variable_get("@form")
  end

  it "saves changes made to a todo" do
    row = @form.row_for_index_path(NSIndexPath.indexPathForRow(0, inSection: 0))
    #row.text_field.text = "Buy 1% Milk" #this blows up, text_field is null
    puts "ROW:: key => #{row.key}, value => #{row.value}, title => #{row.title}"
    # values = @form.to_hash
    # puts "BEFORE ==> #{values}"
    # values[:sections][0][:rows][0][:value] = "Buy 1% Milk"
    # puts "AFTER ==> #{values}"
    # @form.values = values
    @controller.save
  end

end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.