First, declare a variable for the html string of your form:
<script type="text/javascript"> var formHtml = ""; function canRender() { return _canRender; } $(function () { _canRender = false; }); </script>
We use canRender so we can defer the execution of javascript of the form's html string
<div id="editor" style="visibility: hidden"> @using (Html.BeginForm(null, null, FormMethod.Post, new { id = "theForm" })) { <fieldset> <legend>Person</legend> @Html.HiddenFor(x => x.PersonId) @Html.HiddenFor(x => x.RowVersion) <div class="editor-label"> @Html.LabelFor(x => x.Username) </div> <div class="editor-field"> @Html.EditorFor(x => x.Username) @Html.ValidationMessageFor(x => x.Username) </div> <div class="editor-label"> @Html.LabelFor(x => x.Firstname) </div> <div class="editor-field"> @Html.EditorFor(x => x.Firstname) @Html.ValidationMessageFor(x => x.Firstname) </div> <div class="editor-label"> @Html.LabelFor(x => x.Lastname) </div> <div class="editor-field"> @Html.EditorFor(x => x.Lastname) @Html.ValidationMessageFor(x => x.Lastname) </div> <div class="editor-label"> @Html.LabelFor(x => x.Country.CountryId) </div> <div class="editor-field"> <table style="border-style: none"> <tr> <td style="border-style: none"> @Html.AjaxComboBoxFor(x => x.Country.CountryId, "/Countries/Management/Lookup/", "/Countries/Management/Caption/", new { }, new { sub_info = true, can_render_callback = "canRender", textbox_width = 200 }) </td> <td style="border-style: none"> @Html.ValidationMessageFor(x => x.Country.CountryId) </td> </tr> </table> </div> <div class="editor-label"> @Html.LabelFor(x => x.FavoriteNumber) </div> <div class="editor-field"> @Html.EditorFor(x => x.FavoriteNumber) @Html.ValidationMessageFor(x => x.FavoriteNumber) </div> <p> <input type="submit" value="Save" /> <input type="button" id="Closer" value="Close" /> </p> </fieldset> <div style="max-width: 500px; width: 500px;"> @Html.JsAccessibleValidationSummary(excludePropertyErrors: true) </div> } <script type="text/javascript"> $(function () { if (!canRender()) return; var scope = $('#theForm'); parseDynamicContent(scope); $('#Closer', scope).click(function (e) { closeForm($(scope)); }); $('input[type=submit]', scope).click(function (e) { try { e.preventDefault(); if (!scope.valid()) { // alert('has invalid'); return; } save(scope); // closeForm(scope); } catch (e) { alert("Error " + e); } }); $(scope).attr('id', guid()); }); function save(scope) { $.ajax({ url: '/People/Management/SaveViaAjax', type: 'POST', data: $(scope).serialize(), success: function (result) { var isOk = $(scope).modelValidation(result); if (isOk) { var isNew = $('#PersonId', scope).val() == ''; if (isNew) { $('#PersonId', scope).val(result.PersonId); } $('#RowVersion', scope).val(result.RowVersion); if (isNew) { $(scope).closest('table').flexReload(); } else { setFgEditText(scope, 'Username', $('#Username', scope).val()); setFgEditText(scope, 'Firstname', $('#Firstname', scope).val()); setFgEditText(scope, 'Lastname', $('#Lastname', scope).val()); setFgEditText(scope, 'FavoriteNumber', $('#FavoriteNumber', scope).val()); setFgEditText(scope, 'Country', $('#Country_CountryId', scope).ajc().getText()); closeForm(scope); } } // $('#firstTable').flexReload(); }, error: function (a, b, c) { alert(a.statusText); alert(b); alert(c); } }); //ajax }//save </script> </div>
Here's the flexigrid setup and getting the form's html string:
<script type="text/javascript"> $(function () { // main.. setupForm(); setupFirstTable(); // ..main }); function setupForm() { formHtml = $('#editor').html(); $('#editor').remove(); } function setupFirstTable() { $('#firstTable').flexigrid({ url: '/People/Management/List', dataType: 'json', colModel: [ { display: 'User', name: 'Username', width: 150, sortable: true, align: 'left' }, { display: 'Firstname', name: 'Firstname', width: 150, sortable: true, align: 'left' }, { display: 'Lastname', name: 'Lastname', width: 150, sortable: true, align: 'left' }, { display: 'Favorite#', name: 'FavoriteNumber', width: 150, sortable: true, align: 'left' }, { display: 'Country', name: 'Country', width: 150, sortable: true, align: 'left' }, { display: 'RowVersion', name: 'RowVersion', width: 150, sortable: true, align: 'left', hide: true } ], buttons: [ { name: 'Add', bclass: 'add', onpress: add }, { separator: true }, { name: 'Edit', bclass: 'edit', onpress: edit }, { separator: true }, { name: 'Delete', bclass: 'delete', onpress: del } ], singleSelect: true, sortname: 'Lastname', sortorder: 'asc', usepager: true, title: 'Persons', useRp: true, rp: 5, rpOptions: [5, 10, 15, 20, 25, 40], showTableToggleBtn: true, width: 900, height: 'auto', preProcess: function (data) { var rp = getFgRowsPerPage($('#firstTable')); for (i = data.rows.length; i < rp; ++i) { data.rows.push({ 'id': '', 'cell': ['', '', '', '', '', ''] }); } return data; } }); // flexigrid setupGrid($('#firstTable')); } //setupFirstTable function add(com, grid) { try { closeFormByGrid(grid); showAddFormByGrid(grid, formHtml); } catch (e) { alert('error ' + e); } } function edit(com, grid) { closeFormByGrid(grid); var items = $('.trSelected', grid); var item = items[0]; var pk = item.id.substr(3); if (pk.length == 0) return; $.ajax({ url: '/People/Management/GetUpdated/' + pk, type: 'POST', success: function (data) { showEditForm(item, formHtml, function () { var form = $('form', grid); $('#PersonId', form).val(data.Record.PersonId); $('#Username', form).val(data.Record.Username); $('#Firstname', form).val(data.Record.Firstname); $('#Lastname', form).val(data.Record.Lastname); $('input[id=Country_CountryId]', form).val(data.Record.CountryId); $('#FavoriteNumber', form).val(data.Record.FavoriteNumber); $('#RowVersion', form).val(data.Record.RowVersion); $('#Country_CountryId', form).ajc().showCaption(); setFgEditText(grid, 'Username', data.Record.Username); setFgEditText(grid, 'Firstname', data.Record.Firstname); setFgEditText(grid, 'Lastname', data.Record.Lastname); setFgEditText(grid, 'FavoriteNumber', data.Record.FavoriteNumber); }); //showEditForm } //success }); //ajax }//edit function del(com, grid) { var deleteIt = confirm('Do you want to delete the selected record?'); if (!deleteIt) return; var pk = getCurrentRowPk(grid); var version = getFgGridColumnText(grid, 'RowVersion'); // alert(pk + " " + version + " " + encodeURIComponent(version)); $.ajax({ url: '/People/Management/Delete', type: 'POST', data: 'pk=' + pk + '&version=' + encodeURIComponent(version), success: function (result) { if (result.IsOk) { $('#firstTable').flexReload(); } } }); } </script>
Lastly we put this at the end of the html:
<script> $(function () { _canRender = true; }); </script>
Here's the Flexigrid form-inliner helper functions:
function showEditForm(selectedTr, html, assignerFunc) { $(selectedTr).after('<tr class="fgEdit" editId=' + selectedTr.id + '><td width="1" colspan="20" style="border-width: thin; border-top: thick; border-color: #EEE; white-space: normal;"><span></span></td></tr>'); var content = $('td > span', $(selectedTr).next()); // var form = $(content).hide().html(html); var form = $(content).html(html); assignerFunc(); $(content).show(); } function showAddFormByGrid(grid, formHtml) { var tbl = $('.bDiv table', grid); showAddForm(tbl, formHtml); } function showAddForm(tbl, formHtml) { var tbody = $('tbody', tbl); if (tbody.length == 0) { $(tbl).append($('<tbody/>')); tbody = $('tbody', tbl); } $(tbody).prepend('<tr class="fgEdit"><td width="1" colspan="20" style="border-width: thin; border-top: thick; border-color: #EEE; white-space: normal"><span></span></td></tr>'); var content = $('tr td span', tbody); $(content).html(formHtml); }
Flexigrid CRUD(inline form) example with ASP.NET MVC, complete with model validation:
http://code.google.com/p/flexigrid-crud-example/downloads/list
Known issues:
1. Not with flexigrid per se; but when inside of flexigrid, the jQuery Ajax ComboBox's result area is far from its textbox when using Firefox or IE, have made a work-around in Chrome though. If you could lend a help in correcting that problem of jQuery Ajax ComboBox, I'll be more than glad to accept a patch.
2. If the flexigrid has no rows, the inline form is not in full width. Accepting patch for flexigrid code or helper code.
Sample output |
jQuery Ajax ComboBox's detached result screenshot(IE and Firefox problem) |