Updatig a row cell based on user input in other cells

Hi, I am trying to set the “detype” column of the edited row to a constant value ( = “updated!”). When I will succeed doing this I will put some more complex logic to update the column to the correct value.
I was hoping that using the “beforeProcessing” event and setting the field value would do the trick but it does nothing (I mean it all works fine but the column detype stays blank).

Can you help? This is my code (PHP, Yii framework):

CLIENT ========================================



SERVER =============================================

    public function actionGrid_data_hierarchy()
{
            //
            // grid processing and validation
            //
            function insertAuthItemChild($action){
                $item = $_GET['item'];               
                $action->set_value('parent',$item);  
            }
            //
            function updateAuthItemChild($action){
                $item = $_GET['item'];               
                $action->set_value('parent',$item);                    
            } 
            //
            function processAuthItemChild($action){
                // ????           
                $action->set_value('detype','updated!'); 
                // ????
            }                
            //
            // grid configuration
            //
            $item = $_GET['item'];
            require_once("dbconnect.php");
            
            $authorisationlist = array();
            $authorisations = Yii::app()->db->createCommand('
                SELECT id, name, description
                    FROM AuthItem
                    WHERE type in (0,1)
                    ORDER BY description ASC')->queryAll();
            foreach($authorisations as $authorisation) {
                $authorisationlist[$authorisation['name']] = $authorisation['description'];
            }

            $grid = new GridConnector($res, "MySQL");
            $config = new GridConfiguration();
            $config->setHeader("Item,Type");
            $config->setInitWidths('300,*');
            $config->setColTypes("coro,ro");
            $grid->set_config($config);
            
            $grid->set_options("child", $authorisationlist);
            
            $grid->event->attach("beforeInsert","insertAuthItemChild");
            $grid->event->attach("beforeUpdate","updateAuthItemChild");
            $grid->event->attach("beforeProcessing","processAuthItemChild");
            
            $sql = "SELECT C.id, child,
                            CASE type 
                                WHEN 0 THEN 'operation' 
                                WHEN 1 THEN 'task' 
                                WHEN 2 THEN 'role' 
                                ELSE 'illegal type' 
                            END as detype
                        FROM AuthItemChild C
                            INNER JOIN AuthItem ON child = name
                        WHERE parent = '" . $item . "'
                        ORDER BY description ASC";
            
            if ($grid->is_select_mode())
                $grid->render_sql($sql,"id","child,detype");
            else
                $grid->render_table("AuthItemChild","id","child,parent");
}

OK, it seems that this is too hard?

The code which you are using for value modification on server side looks correct. But your data saving config is

$grid->render_table("AuthItemChild","id","child,parent");

which means that updated value will not be saved ( as you are saving only child and parent values )

Hi Stanislav, thanks for your reply but I do not want to save “detype”, I just want to display it.

In such case you need to use beforeRender not beforeProcessing

beforeProcessing event is executed for CRUD operations, and not executed during data loading.

Tried BeforeRender but it does not do what I want.
If I set up the BeforeRender event the column “detype” is set to “Updated!” for all existing rows (I do not want that) but not for newly added or changed rows (which is what I want).

What I want is:

  • the grid should display the data from the render_sql method as I have specified (fine, it does that)
  • when I add a new row and I enter the data in the first column, the grid should display the text “Updated!” in the second column (as I said in my first message, I will then put some logic to actually display a dynamic value and not a text constant).

In such case you need to

a) use beforeProcessing
b) in beforeProcessing handler

function processAuthItemChild($action){ $action->set_response_attribute('detype','updated!'); }

c) on client side

dp.attachEvent("onAfterUpdate", function(sid, action, tid, btag){ var value = btag.getAttribute("detype"); if (value) mygrid.cells(tid, 0).setValue(value); });

Above code will set custom value as attribute of response, and client side code will read that value and change some cell in updated row with new value.

Thank you Stanislav, it’s a step in the right direction although still not what I want because now the “updated!” value appears as soon as I add a new row and not after I have entered the value in the first column. It works fine when updating a row.

Also now I get an error message in Javascript debugging when I try to delete a row, that makes me nervous:

dhtmlx.js
Type Issue
‘null’ is not an object (evaluating c._childIndexes)

Also, there are two problems in the snippets of code you have provided, the first that the
dp.attachEvent(“onAfterUpdate”, function(sid, action, tid, xml) function in my code had an “xml” and not a “btag” attribute. I have changed it but I do not understand the consequences.

The second is that the line
if (value) mygrid.cells(tid, 0).setValue(value);
should be
if (value) mygrid.cells(tid, 1).setValue(value);
because it’s the second column that I want updated.

Don’t get me wrong, this is a marvellous product but I have noted that the documentation is very skinny and is chocked full of errors in the examples (e.g. missing quotes etc.). This does not help people like me that are not and do not want to become Javascript experts but just use the library.

In server side code, instead of beforeProcessing you can use afterUpdate, currently when you adding new row, grid sends data to server and insert new record in DB, which triggers beforeProcessing and custom response to the client side.

AS for js errors, client side onAfterUpdate event will be triggered for all data saving operations, and in case of delete operation it can cause the above error, because on moment of cells() command call the row in question will be already deleted.

If you will change server side code to afterUpdate it must not be a problem anymore.
Also, in client side code you can check value of action parameter which will contain type of server side operation, for which callback is called.

Thank you again Stanislav for your great support. I will give it a go and let you know.

OK, sorted out. :smiley: whew!

The right event to use is a combination of BeforeProcessing (server, PHP) and AfterUpdate (client, JS).
I have tried to find documentation for the set_response_attribute function but I couldn’t find any.

As I said in a previous post you guys have a terrific product but you should really make an effort on the documentation:
1 - have a look at the Yii Framework documentation
2 - for each topic create short, self contained examples that actually work

On the server I got - (get the value supplied by the user in column 1 (child) and use it to get the desired value for column 2 (logic not shown):

   $grid->event->attach("beforeProcessing","processAuthItemChild");

where the function is

        function processAuthItemChild($action){
                $child = $action->get_value('child'); // get the value from first column
                if ($child != "") { // if empty do nothing, otherwise...
                    $detype = 'updated!' // to be changed with correct logic to set detype
                    $action->set_response_attribute('detype',$detype); // this handles the value for detype to the client
                }                                
            }

And on the client:

dp.attachEvent("onAfterUpdate", function(sid, action, tid, btag){
        if (action == "invalid") {
            mygrid.setCellTextStyle(sid, 2, "background:#eeaaaa");
            dhtmlx.message(xml.getAttribute("details"));
        }
        else {
             // get the value from the server
             var value = btag.getAttribute("detype"); 
             // set column 2 (the index is 1, because it's base 0) to value
             if (value) mygrid.cells(tid, 1).setValue(value); 
        }
})