Recommended approach to implementing inline editing for a MVC grid please? - asp.net-mvc

I am using MVC3, C#, Razor, EF4.1
I have implemented grids in their most simple form ie Razor Tables. At present I have implemented editing of record fields off page ie Click "Edit" and the edit page appears, one then fills in data then save which returns user to main grid page.
I need an inline solution where only 1 or 2 fields need updating. Typically the user would either click on the row or on "edit" link and the row would change to "edit mode". One would then edit the data. One would then click on "Save" and the row would resort to read only, or the grid would refresh. Can you recommend a simple and robust solution for this. At present I am not thinking about 3rd party component solutions such as Telerik Kendo UI Grids , although in the near future I will no doubt upgrade to something like this. At present I want to keep it really simple.
Thoughts, wisdom, recommendations appreciated.
Many thanks.
EDIT:
Thanks all. I am going to give these suggestions a try.

Here is simplest way of doing it, see fiddle.
Save all your data using JSON web service. You'll end up having either array of cells or array of array of cells. (Alternatively you can put JSON in a hidden input box)
Use $.data api and put all information needed for server to save in data attributes.
You'll endup having something simple as
var f=$('#myform')
, t = $('table')
, inputs = t.find('input')
, b1 = $('button.save1')
, b2 = $('button.save2')
, ta = $('#save')
// update data-val attribute when value changed
t.on('change', 'input', (e) => $(e.target).data('val', e.target.value))
// store everything in $.data/data-* attributes
b1.on('click', () => {
var data = []
inputs.each((i,inp) => data.push($(inp).data()) )
ta.text(JSON.stringify(data))
})
// use $.serialize
b2.on('click', () => {
var data = f.serializeArray()
ta.text(JSON.stringify(data))
})
input {border : 1px solid #fff;margin:0; font-size:20px; }
input:focus { outline: 1px solid #eee; background-color:#eee; }
table { border : 1px solid #999; border-collapse:collapse;border-spacing:0; }
table td { padding:0; margin:0;border:1px solid #999; }
table th { background-color: #aaa; min-width:20px;border:1px solid #999; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name='myform' id='myform'>
<table>
<tr>
<th></th>
<th>A</th>
<th>B</th>
<th>C</th>
</tr>
<tr data-row="0">
<th>1</th>
<td><input type="text" data-row="0" data-col="0" data-val="a" value="a" name='data[0][0]'/></td>
<td><input type="text" data-row="0" data-col="1" data-val="b" value="b" name='data[0][1]'/></td>
<td><input type="text" data-row="0" data-col="2" data-val="c" value="c" name='data[0][2]'/></td>
</tr>
<tr data-row="1">
<th>2</th>
<td><input type="text" data-row="1" data-col="0" data-val="d" value="d" name='data[1][0]'/></td>
<td><input type="text" data-row="1" data-col="1" data-val="e" value="e" name='data[1][1]'/></td>
<td><input type="text" data-row="1" data-col="2" data-val="f" value="f" name='data[1][2]'/></td>
</tr>
<tr data-row="2">
<th>3</th>
<td><input type="text" data-row="2" data-col="0" data-val="g" value="g" name='data[2][0]' /></td>
<td><input type="text" data-row="2" data-col="1" data-val="h" value="h" name='data[2][1]' /></td>
<td><input type="text" data-row="2" data-col="2" data-val="i" value="i" name='data[2][2]' /></td>
</tr>
</table>
</form>
<div name="data" id="save" cols="30" rows="10"></div>
<button class='save1'>Save 1</button>
<button class='save2'>Save 2</button>
Given that you generate your table in Razor view and don't need to load data into table. So you "loading" data on the server and saving changes with tiny JS snippet above.
You can also style your input cells in the table so they would look different when with focus and not, making it look like Excel spreadsheet (without fancy Excel features though, just look).

Well in that case I will suggest you to add a div with a unique id with each grid row.
and on the click of edit button insert a row having text boxes with value using java script.

Using knockout.js is my preferred approach, and in my opinion, is simple to get started with but flexible enough to keep up with project demands.
Here are examples:
http://www.knockmeout.net/2011/03/guard-your-model-accept-or-cancel-edits.html
http://knockoutjs.com/examples/gridEditor.html
If you think this is for you then take an hour or two and go through the tutorials, it's well worth the time:
http://learn.knockoutjs.com/

I have implemented exactly what you are asking for, but I cannot assure you that it is robust. It definitely is not simple. Based on the article Get the Most out of WebGrid in ASP.NET MVC by Stuart Leeks I have created an MVC project which I have heavily modified with my own javascript. In the end I have come up with a solution that works but could be vastly improved. Took me at least a week to implement.

I write tutorial for implementing inline editable grid using mvc, knockoutjs with source code:
http://www.anhbui.net/blog?id=kojs-1

Related

Why does Safari Mobile have trouble handling many input fields on iOS 8

iOS 8.0/8.0.1/8.0.2 has this problem.
I have a page with 70 simple text inputs:
<input class="" type="text">
On iOS 7 the page has no problems. But on iOS 8, selecting and typing in a field causes the iPad to become slow and laggy.
You can see an example of the problem in this jsFiddle
Does anyone know a fix to this problem???
Seems the issue is related to the number of text inputs which are part of the document or a form.
I "fixed" the issue by placing <form> tags around small groups of text inputs.
<form>
<input type="text">
<input type="text">
<input type="text">
</form>
<form>
<input type="text">
<input type="text">
<input type="text">
</form>
etc.
In some cases I had large tables with individual text fields in the <td> elements. You can't include <tr> or <td> elements in a form but rather must include the whole <table> or the content of individual <td> elements. In those cases I had to place a <form> element around each text input.
<table>
<tr>
<td>
<form>
<input type="text">
</form>
</td>
<td>
<form>
<input type="text">
</form>
</td>
</tr>
etc....
</table>
Update: This appears to be resolved in the iOS 8.1.1 beta. It appears not to be fixed, based on comments. :(
It's also in the 8.1 betas. You should file a radar.
Some stuff causes the entire webpage to reload or Safari to hang. For example, visit http://getemoji.com/ and start typing in the search box. You can't do it on an iOS 8.x device without the page reloading.
Notably, Chrome and Mercury work fine, so you could suggest that your users switch to third-party browsers based on UIWebView. (I didn't test out WKWebView.)
I've been struggling with this for many hours until I found the solution on this page. Thanks! This is my implementation of solution suggested by Design Navigator:
$(document).ready(function(){
var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1 && navigator.userAgent && !navigator.userAgent.match('CriOS');
if (isSafari){
$('#container input[type="text"]').wrap('<form />');
}
}

Programmatically log into a website

I am trying to write a quick application to view my electric bills programatically. For that I need to be able to log into the website programmatically before I can move ahead with anything else.
I know that one has to use curl in some way for that. But, I am not sure how I can leverage curl to log into the website through terminal. Here is the website: Seattle Utilitiy Bills Website
Looking at the corresponding source for the login form, it look like this:
<tr>
<td nowrap class="form-style-text">User ID:</td>
<td class="form-style-label"><input type="text" autocomplete="off" size="17" name="loginid" maxlength="32"></td>
</tr>
<script type="text/javascript">document.wizForm.loginid.focus()</script>
<tr>
<td class="form-style-text">Password:</td>
<td class="form-style-label"><input type="password" autocomplete="off" name="password" size="17" maxlength="16"></td>
</tr>
<tr>
<td class="form-style-text"> </td>
<td align="left">
<input name="login" type="submit" class="actionbutton" onClick="doLogin()" value="Log in"/>
</td>
</tr>
I know I need to use curl in some way to be able to log in, but I am not sure how. Specially because the login logic is being done by the 'doLogin()' function, and I am not sure how I can call that function from the terminal using curl. Here is the definition of the 'doLogin()' function:
function doLogin() {
var wform = document.wizForm;
wform.type.value='LoginMenu';
}
Any clues how I can log into this page using terminal/curl?
You missed the form tag. <form class="extform" action="/csg/inetSrv" method="post" name="wizForm">
Most likely you need to save a session cookie after you logged in.
What you need to do is use curl to post the form-data to /csg/inetSrv. use the parameter --cookie-jar <file> to save the cookie. Then you can use curl again to make requests with the cookie file and you are logged in.
It might be easier to check the cookie in a browser first to understand how it is used. You can then try using curl with the browsers session cookie to test before you use curl to log in.

Setting TD value by class

I have below code in a form for which i don't have access to and can not write any code. But in my webpage i have created another form where i can write some script.
My requirement: I have a dropdown and on selection of value from this i need to change the value of another drop-down field which is in different drop-down.
I tried the below script but not working.
Appreciate any help regarding this. Coding is not my profession but i am willing to learn.
enter code here
<script type="text/javascript">// <![CDATA[
function doStuff() {
alert($('#donation_campaign').val());
$('#PC1184$ddlDesignations').html($('#donation_campaign').val());
}
// ]]></script>
<h1>Thank you for support</h1>
<p> </p>
<p><label>Select your supporting chapter</label> <select id="donation_campaign" name="donation[campaign]" onchange=" doStuff()"><option value="Corpus Fund">DC Metro</option><option value="8">Boston</option><option value="13">AZ</option><option value="24">Austin</option><option value="13">JDU</option><option selected="selected" value="13">Common Pool</option></select></p>
form code for which i dont have access to:**
<tr id="PC1184_trDesignation">
<td class="BBFieldCaption DonationFieldCaption DonationFieldDropDownCaption">
<label for="PC1184_ddlDesignations" id="PC1184_lblDesignationCaption">Designation:</label>
</td>
<td colspan="2" class="BBFieldControlCell DonationFieldControlCell">
<select name="PC1184$ddlDesignations" id="PC1184_ddlDesignations" class="BBFormSelectList DonationSelectList">
<option selected="selected" value="8">General Unrestricted Fund</option>
<option value="13">Corpus Fund</option>
<option value="24">Education Fund</option>
</select>
</td>
</tr>
Thanks in advance,
Naveen
The script tag is processed by browser at the moment it appears in the HTML, the code is executed at that very moment. To postpone the execution, you should bind the code you've written to later event, like page load:
$(document).ready(doStuff);
Also, your function seemingly needs to be called everytime when first element is changed. So you need to bind it to change event of this element as well.
$('#donation_campaign').change(doStuff);
put these two lines at the end of your script.
At first, simplest solution is to have updateEverything javascript function that calculates all dependencies and modifies all necessary elements on the page, ensuring everything is correct. And you call this function at the page load and at changing of any element that is involved in dependencies tracked.

Paginated, sortable, collapsible datarows (tables) in mobile application

I want to implement the Demo shown at http://tablesorter.com/docs/example-pager.html in a mobile application. I want each row in the Demo to be collapsible/expandable. What is the best way to achieve it? To my knowledge tables don't work well in mobile applications. Correct me if I am wrong. Thanks.
== EDIT ==
This is almost all I want
http://stokkers.mobi/jqm/tableview/demo.html
I'm not sure how this will do in a mobile application, but check out this demo. No need to download that mod as it was added to tablesorter 2.0.5.
The demo shows how to use an undocumented option named cssChildRow which contains the class name expand-child. This class name is added to a table row tr to attach it to the row before it (example code from that demo):
<tr>
<td rowspan="2" class="collapsible"></td>
<td rowspan="2" class="collapsible_alt">SO71774</td>
<td>Good Toys</td>
<td>PO348186287</td>
<td>Jul 20, 2007</td>
<td>$972.78</td>
</tr>
<tr class="expand-child">
<td colspan="4">
<div class="bold">Shipping Address</div>
<div>
99700 Bell Road<br /> Auburn, California 95603
</div>
</td>
</tr>
The code needed to make the rows collapsible in in this file: jquery.tablesorter.collapsible.js

Knockout Javascript any strategies for making a foreach checkbox section with a bound observable array

Basically I'm making a repeatable section and I want to have the checked state of all checkboxes pre-supplied by an array.
<div style="height: 100%; border: 1px solid grey; overflow-y: scroll;" id="AssociatedUsers" data-bind="foreach: AllUserList">
<input type='checkbox' class='cSupUser' style="width:20px;margin:2px" value="$data" data-bind='checked: supplierUsers' /><span data-bind='text: $data.Text'></span><br />
</div>
But obviously value="$data" is just returning the string "$data". I've decided to start working on a solution where I just map the array with json strings when I save and load the related data, but this adds complication and feels like a hack, so I was wondering if there is a better way to handle this situation. I would also prefer supplierUsers could just be mapped directly to the viewModel, because I'm going to be generating the response to the server from the viewModel, but it seems like observableArrays don't work for that parameter.
I'm only 3 days into using knockout framework, any help/suggestions are appreciated.
The way i've dealt with this is to use the attr binding for each checkbox. E.G.
<input type="checkbox" data-bind="checked : supplierUsers, attr : { value : $data}" />

Resources