The code in this article was updated to be compatible with version 10.x of PHPRunner, ASPRunner.NET and ASPRunnerPro.

Similar to Excel-like grid discussed in previous article this technique helps you to achieve similar goals. Instead of bringing up the whole edit page you can click that single field you need to edit, change its value and see your changes posted to the database automatically.


Click any of fields that are enabled for inline editing. Text will turn into edit control, the way it were setup in PHPRunner, ASPRunnerPro or ASPRunner.NET. To exit editing hit Esc button on your keyboard or click anywhere outside of edit control. Changes will be saved automatically.

Note that this code is designed to work with tables that only have a single key column selected. While making it work with multiple key columns is possible we didn’t want to over-complicate this example.

To make this happen select one or more fields to be editable inline and add the following code to List page: Javascript OnLoad event.

Code

PHPRunner

$(document).ready(function() {  
  
    var $elem;  
    var key;  
    var field;  
    var val;  
  
    function cancelEditing() {  
        if ($grid.data("editing")) {  
            $elem.html(val);  
            $grid.data("editing", false);  
            $elem.closest("td").css("padding","5px 8px");  
        }  
    };  
  
  
    $(document).keyup(function(e) {  
        if (e.keyCode == 27) {   
            cancelEditing();  
        }  
    });  
  
  
    $("span[id^=edit]").attr('title', 'Click to edit');  
  
        $grid=$(document.body);  
        $grid.on("click", function(e) {  
  
        // click during editing outside of edited element   
        if ($grid.data("editing") &&   
                !$(e.target).is(":focus")   ) {  
            cancelEditing();  
            return;  
        }  
  
        // click  on one of editable elements?  
        if( $grid.data("editing") ||  
                !$(e.target).attr("id") ||  
                !$grid.data("editing") && $(e.target).attr("id").substring(0, 4) != "edit"  
            ) {  
            return;  
        }  
  
        $elem = $(e.target);  
        // enter editing mode  
        val = $elem.html();  
  
        $grid.data("editing", true);  
          
        var id = $elem.parent().attr("data-record-id");  
        var res=$elem.attr("id").match(/[^_]+$/);  
        field = res[0];  
  
        var gridrows = JSON.parse(JSON.stringify(pageObj.controlsMap.gridRows));  
        for (var i = 0; i < gridrows.length; i++) {  
            if (gridrows[i].id==id) {  
                key=gridrows[i].keys[0];  
                break;  
            }  
        }  
  
        // prepare request  
        var data = {   
            id: id,  
            editType: "inline",  
            editid1: key, 
				page: "list",
            isNeedSettings: true  
        };  
  
        // get edit controls from the server  
        $.ajax({  
        type: "POST",  
        url: "carscars_edit.php",  
        data: data  
        }).done(    function(jsondata) {  
            var decoded = $('
').html(jsondata).text(); response = jQuery.parseJSON( decoded ); // clear error message if any if ($elem.next().attr('class')=="rnr-error") $elem.next().remove(); // cmake control as wide as enclosing table cell width = $elem.closest("td").width(); $elem.html(response.html[field]); if (response.html[field].indexOf("checkbox")<0) { $elem.find("input,select").width(width-5).focus(); $elem.closest("td").css("padding","1px 1px"); } }); }); $grid.data("editing", false); // save function $(document.body).on('change','input[id^=value],select[id^=value]',function() { var data = { id: 1, editType: "inline", a: "edited", page: "list", editid1: key }; var type = $(this).attr('type'); if (type) type=type.toLowerCase(); else type="text"; // regular field or check box if (type!="checkbox") { data["value_"+field+"_1"]=$(this).val(); } else { if($(this).is(":checked")) { val="on"; } data["value_"+field+"_1"]=val; data["type_"+field+"_1"]="checkbox"; } // clear error message if any if ($(this).next().attr('class')=="rnr-error") $(this).next().remove(); // save data $.ajax({ type: "POST", url: "carscars_edit.php?submit=1", data: data }).done( function(jsondata) { var decoded = $('
').html(jsondata).text(); response = jQuery.parseJSON( decoded ); if (response["success"]==false) { $('
').insertAfter($elem).html(response["message"]); } else { $elem.html(response["vals"][field]); $grid.data("editing", false); $elem.closest("td").css("padding","5px 8px"); } }); }); });

You will have to modify the Edit page URL accordingly to your project settings. Replace products_edit.php with corresponding name of your table i.e. tablename_edit.php.

ASPRunnerPro

Replace products_edit.php with corresponding name of your table i.e. tablename_edit.asp.

ASPRunner.NET

No changes are required. Code goes to List page: Javascript OnLoad event.

$(document).ready(function() {  
  
    var $elem;  
    var key;  
    var field;  
    var val;  
  
    function cancelEditing() {  
        if ($grid.data("editing")) {  
            $elem.html(val);  
            $grid.data("editing", false);  
            $elem.closest("td").css("padding","5px 8px");  
        }  
    };  
  
  
    $(document).keyup(function(e) {  
        if (e.keyCode == 27) {   
            cancelEditing();  
        }  
    });  
  
  
    $("span[id^=edit]").attr('title', 'Click to edit');  
  
        $grid=$(document.body);  
        $grid.on("click", function(e) {  
  
        // click during editing outside of edited element   
        if ($grid.data("editing") &&   
                !$(e.target).is(":focus")   ) {  
            cancelEditing();  
            return;  
        }  
  
        // click  on one of editable elements?  
        if( $grid.data("editing") ||  
                !$(e.target).attr("id") ||  
                !$grid.data("editing") && $(e.target).attr("id").substring(0, 4) != "edit"  
            ) {  
            return;  
        }  
  
        $elem = $(e.target);  
        // enter editing mode  
        val = $elem.html();  
  
        $grid.data("editing", true);  
          
        var id = $elem.parent().attr("data-record-id");  
        var res=$elem.attr("id").match(/[^_]+$/);  
        field = res[0];  
  
        var gridrows = JSON.parse(JSON.stringify(pageObj.controlsMap.gridRows));  
        for (var i = 0; i < gridrows.length; i++) {  
            if (gridrows[i].id==id) {  
                key=gridrows[i].keys[0];  
                break;  
            }  
        }  
  
        // prepare request  
        var data = {   
            id: id,  
            editType: "inline",  
            editid1: key,  
	    page: "list",
            isNeedSettings: true  
        };  
  
        // get edit controls from the server  
        $.ajax({  
        type: "POST",  
        url: "edit",  
        data: data  
        }).done(    function(jsondata) {  
            var decoded = $('
').html(jsondata).text(); response = jQuery.parseJSON( decoded ); // clear error message if any if ($elem.next().attr('class')=="rnr-error") $elem.next().remove(); // cmake control as wide as enclosing table cell width = $elem.closest("td").width(); $elem.html(response.html[field]); if (response.html[field].indexOf("checkbox")<0) { $elem.find("input,select").width(width-5).focus(); $elem.closest("td").css("padding","1px 1px"); } }); }); $grid.data("editing", false); // save function $(document.body).on('change','input[id^=value],select[id^=value]',function() { var data = { id: 1, editType: "inline", a: "edited", page: "list", editid1: key }; var type = $(this).attr('type'); if (type) type=type.toLowerCase(); else type="text"; // regular field or check box if (type!="checkbox") { data["value_"+field+"_1"]=$(this).val(); } else { if($(this).is(":checked")) { val="on"; } data["value_"+field+"_1"]=val; data["type_"+field+"_1"]="checkbox"; } // clear error message if any if ($(this).next().attr('class')=="rnr-error") $(this).next().remove(); // save data $.ajax({ type: "POST", url: "edit?submit=1", data: data }).done( function(jsondata) { var decoded = $('
').html(jsondata).text(); response = jQuery.parseJSON( decoded ); if (response["success"]==false) { $('
').insertAfter($elem).html(response["message"]); } else { $elem.html(response["vals"][field]); $grid.data("editing", false); $elem.closest("td").css("padding","5px 8px"); } }); }); });

41 thoughts on “In-place editing

  1. In-place editing and Excel like grid in PHPRunner applications are exactly what I keep hearing for request. Outstanding job! These tips that you produce is what make phpRunner number 1.

  2. Looks good, I know its not ready, but found a bug. :)

    Click on Unit price to edit. Click on Quantity to Edit. Update Unit price and click off. Quantity will update with the value put into Unit price, and Unit price will still be open for edit.

    But if you can get that fixed, this would be very handy.

    Especially, if its a check box field, one click will toggle it, that would make it really good. :)

  3. @Ausmonty,

    you should not be able to open more than one edit control at the time. Click anywhere outside of edit control closes it.

    Just in case, what browser do you use? Cannot reproduce it.

  4. var decoded = $(‘
    ‘).html(jsondata).text();
    response = jQuery.parseJSON( decoded );

    Getting a compilation error: Unterminated string constant in line 70

  5. I don’t know if you have done anything, but it seems to be working fine now. I can only select one field at a time. Fantastic. :)

  6. Seems I might have spoken to soon. Something wierd is happening, it is now broken again. :( I am doing this on the demo. Will ahve to give it a try in one of my apps.

  7. Might have found something that is causing it. If I douple click to open it, the problem occures. If I single click, all is good. I do ahve a habit of double clicking things.

    Also have noted that when I put a price in for less than 20, it comes up with the message about minimum of 20, no probs. but when I then change it to above 20, it accepts it, but the message about needs to be above 20 remains.

  8. data: data
    }).done( function(jsondata) {
    var decoded = $(‘
    ‘).html(jsondata).text();
    response = jQuery.parseJSON( decoded );
    if (response[“success”]==false) {
    $(”
    “).insertAfter($elem).html(response[“message”]);
    }
    else {

    Errors in the above as well?!?

    Help

  9. Great Job. I have tried it and a dropdown works, but not a checked box, yet they are both selected on inline edit. I see on the live demo that the checkboxes show yes / no until you click on them, then they show a tick or not, maybe that is the difference? Could it be?

  10. Where is the specific field identified? I see where we change the table name but where do you indicate the field that it is to be used on. I added it to the edit page and javascript section as indicated but I don’t see any inline editable that works like you example.

  11. @Don,

    editable fields are defined in the project itself. You just need to add this code to correct event, which is “List page: Javascript OnLoad”.

  12. @Don
    You copy and paste the code in the List Page – Javascript onload.
    There are two lines you need to change. As you can see above, search for products_edit.php which is in the code you copied. Then change the products for your own table name so it could be job_edit.php, or cars_edit.php.

    In the fields on you project, whatever you select as Inline edit will have the option to be editable from the list page.

  13. Yep agree with Paul, if the check box field is shown as a check box, it does not work. I changed my project to use Yes/No, and it works.

    Small issue, for a great enhancement.

  14. To get it working on a checkbox, I had to set the Edit as a Checkbox, but the View as Text. It displays Yes or No. Its no great deal, and it works, but I will have to re-size my columns now as I had 4 checkboxes in line for different status of jobs, but I am sure it will work and the customer will be happy with this mod, as now they can edit an engineer and select the job status all on the same page and not have to go into Edit, change it and save it and back to the list to print it. So Yes, I am more than happy with this bit of FREE code. Great job Xlinesoft

  15. Excellent contribution. Implemented by example in one of my lists page, everything works except that does not save changes.

    Any suggestions?

    Thanks.

  16. This is EXACTLY what I was looking for.

    Now, if only I could change the color of the text, the size and the font without writing it into the database – all would be perfect (when it writes it to the database, it messes with sorting and other problems).

    Mike

  17. I couldn’t get this to work on a form with only a single checkbox per row that is editable. I took the previous comments into account, changed the checkbox to text, and selecting it gets the editable checkbox. After that, the checkbox doesn’t have focus, the edit_link has focus, so clicking the checkbox to update it’s value causes the script determine that “something other than the current focus element has been clicked” and it cancels the edit before it can save. I’ve tried forcibly setting the focus but it still loses it before the next click.

    I’ve had to abandon it there for now.

  18. I am getting an error while implementing this code, when the field name contains “_”.
    Is there a work around available for this?

    Nitin

  19. I’m getting this error with the .net code
    Uncaught TypeError: Cannot read property ‘indexOf’ of undefined

  20. Hi, does anybody know if it is applicable to master-details tables as well?
    If yes, what is the correct statement at line 130?
    e.g. if the details table is called product_details, then what is the correct statement on line 130?
    should it be
    url: “product_details_edit.php?submit=1”,

    thanks

  21. Interesting stuff, I just stumbled upon here :)
    only works on my text fields though so far in phprunner 9.8
    Any idea how to get this to work with cascading lookup fields I’m using? Got two fields that are both dropdowns and dynamically update each other (AgentGroup & Agent)
    thanks

  22. and another question … how would it be possible to use this event to click on a previously EMPTY field (for example State field is missing where Country requires one?)
    thanks

Leave a Reply

Your email address will not be published. Required fields are marked *