Search code examples
jqueryjquery-mobileknockout.jsknockout-mapping-plugin

knockout jquerymobile collapsible panel with edit and cancel/save


I'm having some issues with knockout binding to a collapsible panel (for mobile) and am hoping that someone can help.

Here's what I'm trying to accomplish:

  1. I have a form with a summary, and dynamically created panels. On these panels, the header is bound to a Branch Name. Content contains summary info.

  2. Within each [Branch Name] heading, I'd like to add an "Edit" button (on the right) which, when clicked, would a) replace itself with "Save" and "Cancel" buttons ad b) hide all other "Edit" buttons in the remaining sections. When the Save or Cancel action is invoked, All Edit buttons are visible again.

  3. When in Edit mode, I'd like the label to be replaced with an input field

And of course I'm assuming all of this would require custom [ko] bindings - but I just can't seem to figure it out.

Thanks in advance!

<div data-role="collapsible" data-collapsed="false" data-mini="true" data-theme="a" data-inset="false" data-collapsed-icon="arrow-d" data-expanded-icon="arrow-u" data-enhance="true">
<h4><span data-bind="text: Name"></span>
    This is where I'd like the EDIT, SAVE and CANCEL buttons
</h4>

<div class="ui-grid-a">
    <div class="ui-block-a">Bulk Interest</div>
    <div class="ui-block-b"><span data-bind="text: Interest"></span>
    </div>
    <div class="ui-block-a">Adjustments</div>
    <div class="ui-block-b"> <span data-bind="text: Adjustments"></span>
    </div>
    <div class="ui-block-a">Current</div>
    <div class="ui-block-b"><span data-bind="text: Current"></span>
    </div>
</div>

PS: Here's a sample Fiddle (http://jsfiddle.net/sal_andani/pvsky/)


Solution

  • The way I typically handle this problem is as follows:

    For the editable record, in this case a branch, in declaring the model (say through a new BranchModel() constructor) I create an editing attribute on the model which defaults to false. I can then add buttons with functions:

    <input type="button" data-bind="click: edit, visible: !editing()">edit</input>
    <input type="button" data-bind="click: delete, visible: !editing()">delete</input>
    <input type="button" data-bind="click: save, visible: editing()">save</input>
    <input type="button" data-bind="click: cancel, visible: editing()">cancel</input>
    

    With edit and cancel functions on the model:

    this.edit = function() { this.oldModel = this.get(); this.editing = true; }
    this.cancel = function() { this.set(this.oldModel); this.editing = false; }
    

    Finally, in the form itself I can pull the same trick above as with the buttons:

    <span class="field">Field</span>
    <span class="value" data-bind="text: value, visible: !editing()"></span>
    <input class="value" data-bind="value: value, visible: editing()" />
    

    Thus, we have a basic system for viewing and editing a model. There was a lot to your question, but I hope this gives you a good direction on how to handle some of the more general cases (like disabling edits on ALL models when one is in edit mode).