Best way to reset a form using Cairngorm?

I just implemented some code that doesn’t feel quite right, but works and would like your input on the matter. A Payment Entry form will be used by the user several times in the life of a Flex application to enter different type of payments. So every time the user wants to pay, the form needs to cleared. I can see these different ways:

1. Ask the form to clear all it’s fields

2. Bind the fields to a model, and reset the model with the default fields values

3. Create a new instance of the form.

It’s a rather complex form with multiple steps (tabs) and the user can quit the form at any moment. So option 1 and 2 needs to reset not only the fields but also the state of each component used on the form. Therefore I opted for approach three which goes as follows:

The view contains following code that replaces the form with a new instance:

public function clearPaymentInformation():void {
	var index:Number =  content.getChildIndex(enterPaymentView);
	content.removeChild(enterPaymentView);
	enterPaymentView = new EnterPaymentInformation()
	content.addChildAt(enterPaymentView, index);
}

Now we have a PayInvoiceCommand that needs to invoke this function. That’s where what doesn’t feel right as the command has to know the view. With the newer version of Cairngorm the command gets information using a delegate, then updates the model. The view is bound to the model. But the command shouldn’t have to know the view. But for option 3 I didn’t find another way around. So I use an adapted version of the ViewLocator (as my view are not ViewHelpers) to which I register the view upon creation. Then in the command I use

WebComponentsViewLocator.getInstance().getView("paymentView").clearPaymentInformation();
model.paymentViewState = WebComponentsModelLocator.PAYMENT_VIEW_STATE_ENTER_PAYMENT;

Is there anyone out there that uses the same approach. If no, thats maybe a good answer that I am on the wrong track. Maybe I should issue an event from the command and have the view listen to the event. This would decouple both, but still doesn’t feel quite right. Maybe I just had a too long day. So any insight is welcome on how you deal with “reseting” forms in your Cairgorm applications. Thanks in advance.

Time for MotorStorm!

Posted by Daniel Wanja Fri, 16 Mar 2007 04:29:57 GMT


Comments

  1. John Wilger about 1 hour later:

    Not sure if this would be the /best/ way to go, but if you have the form tied to a model object and the command modifies that model object, you could always have the command tell the model object to dispatch an event which the view object will listen for and handle by resetting itself. This way the command doesn’t need to know about the particular view that is accessing that model. It also ensures that if you ever have other view components accessing that model, they can be reset at the same time just by listening for and handling this event.

  2. JesterXL about 2 hours later:

    I agree with John. Option A is just to bind your Forms data fields to the ModelLocator. If this is too hard for #2, even if you put a binding tag to run a function that resets state, you’re better off:

    1. building each form as a component
    2. expose getter / setters as bindable
    3. either have the getter / setters do the whole commitProperites route where they set the controls, OR just bind the controls to the internal copy
    4. build a controller View; a View who’s sole job is to contain the component, bind it’s getter / setters to the ModelLocator, and call methods on it to reset it’s data and state if necessary.

    A lot of developers give tasks to the Command that a View is more than capable of handling, more appropritae to do so, AND results in more re-usable components that have no clue what a ModelLocator is. You can still build the form around your Value objects, and even expose reset methods. The parent view is the one who knows about ModelLocator and Cairngorm event dispatching.

    Rule of thumb; if you start using ViewLocator, blog like you just did for other ways.

  3. Olivier Stembert about 2 hours later:

    You can easily implement what you want with the Observe tag.

    Take a look at http://weblogs.macromedia.com/paulw/

  4. Dimitrios Gianninas about 18 hours later:

    Bind your model object to the view, like so:

    Then once the command has finished doing its work, reset the object

    ModelLocator.paymentInfo = new PaymentInfo();

    and thus in your view should reset itself depending on how it is coded.

  5. Dimitrios Gianninas about 18 hours later:

    Bind your model object to the view, like so:

    [mx:MyForm dataProvider=“{ModelLocator.paymentInfo}”/]

    Then once the command has finished doing its work, reset the object

    ModelLocator.paymentInfo = new PaymentInfo();

    and thus in your view should reset itself depending on how it is coded.

  6. Daniel Wanja about 22 hours later:

    Thanks for all the great feedback. I followed the link Oliver proposed which led me to the solution which I felt most appropriate in my case. The com.adobe.ac.Observer class allows the view to listen to the model and invoke a method on the view that allow to reset the form. The command just need to change the model. This allowed to get rid of the ackward ViewLocator. I believe this is appropriate for situation I am in as it’s a pure data entry form which doesn’t need to be linked to a value object (or model). So to clear the view I just use the removeChild/addChild and get a brand new view with all the fields clears, validators intialized, all the tab navigator and other selection set correctly. Cool.

    Now the command indicates that the entry form needs to be reset just by modifying a “form counter” on the model:

    model.resetPaymentForm += 1;  //TODO: encapsulate implementation

    The view uses the com.adobe.ac.* packages and declares an observer to the resetPaymentForm.

    <observer:Observe	source="{WebComponentsModelLocator.getInstance().resetPaymentForm}"
    	handler="{clearPaymentInformation}"
    />

    And the clearPaymentInformation just creates a new instance of the entry form.

    Thanks guys!

  7. Daniel Brockman 8 months later:

    That seems like a weird kludge. Why not simply use a regular event?