⚠ In case you've missed it, we have migrated to our new website, with a brand new forum. For more details about the migration you can read our blog post for website migration. This is an archived forum. ⚠

  •     

profile picture

read only field form set_relation_n_n()



jean-baptiste

jean-baptiste
  • profile picture
  • Member

Posted 01 March 2013 - 16:24 PM

Is there any way to display a field from a set_relation_n_n as read only ?

 

For instance, I have an "oeuvre" table linked to an "auteurs" table by a n_n relation and don't want the "auteur" field to be editable, only to display the lists of the "auteurs" linked to the "oeuvre" (see screen capture).

 

[attachment=485:Mozilla Firefox_2013-03-01_17-05-33.png]

 

I wrote a callback to replace the edit field by the names of the authors :

 

    public function oeuvre()
    {    
        $crud = new grocery_CRUD();
        $crud->set_table('oeuvre');
        $crud->set_relation_n_n('auteurs', 'ecrit_oeuvre', 'personne', 'id_oeuvre', 'id_personne', 'nom', 'ordre');
$crud->callback_field('auteurs',array($this,'callback_affiche_formulaire_auteurs'));
        $crud->columns('titre','descriptif','auteurs');
        $output = $crud->render();
        $this->_prelib_output($output);        
    }       

function callback_affiche_formulaire_auteurs($value, $primary)
    {
        $liste_auteurs = '';
        $nom_usuel = '';
        $prenom_etat_civil = '';
        $this->db->where('id_oeuvre',$primary); 
        $query_ecrit_oeuvre = $this->db->get('ecrit_oeuvre');
        ... 
        }
        return $liste_auteurs;
    }    

 

But as not expected, grocerycrud deletes the author-work (work = oeuvre) relation if I edit and save the form ... Is there a clever way to prevent this ? Is there a way to pass to GC the value of the field before update ?

 

 
 


davidoster

davidoster
  • profile picture
  • Member

Posted 03 March 2013 - 10:56 AM

There you are: /topic/345-solved-using-set-relation-with-callback-column-problem/


jean-baptiste

jean-baptiste
  • profile picture
  • Member

Posted 11 March 2013 - 13:53 PM

Thanks, but it doesn't fit for this problem.


jean-baptiste

jean-baptiste
  • profile picture
  • Member

Posted 11 March 2013 - 16:15 PM

I figured that GC checks the readonly status of relation_n_n fields before database update (see db_update). But GC don't take into account the following :

 

$crud->field_type('auteurs','readonly');

 

Do you know why ? Could GC take readonly type for relation_n_n fields into account ?


jean-baptiste

jean-baptiste
  • profile picture
  • Member

Posted 14 March 2013 - 13:00 PM

Salut les gars,

I have found the solution of my problem. As said Kenta Saito for the set_relation, you have to use a callback to replace the form field by it's (read-only) value. The difference is, when you write a callback for a 1-n relation, the id of the related field is a SQL field of the displayed table (for instance, the id of the country where a book was written). But in a n-n relation (for instance, a relation between "book" and "author" tables, through a "written_by" table), there is no SQL field in the "book" table to apply the callback. The solution is to declare by the meaning of the GroceryCrud fields() function, an HTML field, not related to any SQL field, which the callback would be applied.

 

For instance, if we have a "oeuvre" table with "titre" and "descriptif" fields, with a n-n relation with an "auteurs" table, throught a link table "ecrit_oeuvre", you would usualy write the following to display the "oeuvre" form :

 

public function oeuvre()
{    
    $crud = new grocery_CRUD();
    $crud->set_table('oeuvre');
    
    $crud->set_relation_n_n('auteurs', 'ecrit_oeuvre', 'personne', 'id_oeuvre', 'id_personne', 'nom', 'ordre');
    $output = $crud->render();
    $this->_prelib_output($output);        
}       

 

Now, if you want to display the "auteurs" field as read only, you could write the following :

public function oeuvre()
{    
    $crud = new grocery_CRUD();
    $crud->set_table('oeuvre');
    
    // Do not declare the read-only field by a set_relation_n_n
    /// $crud->set_relation_n_n('auteurs', 'ecrit_oeuvre', 'personne', 'id_oeuvre', 'id_personne', 'nom', 'ordre');
    $crud->callback_field('auteurs',array($this,'callback_field_auteurs'));
    // Explicitly declare the read-only form field (note that this field has no equivalent in the database table, its only an HTML form field)
    // in the contrary, the 'titre' HTML field is linked to a field in the 'oeuvre' MySQL table
    // In this example, the read-only field is 'auteurs', 'titre' and 'descriptif' are the table 'oeuvre' fields
    // as this read-only field has no equivalent in the SQL tables, you can name it a as you want.
    // Since GroceryCrud has no function to add only one HTML field, you have to explicitely declare all the displayed fields with the fields() function
    $crud->fields('titre','descriptif','auteurs');
    $output = $crud->render();
    $this->_prelib_output($output);        
}       

function callback_field_auteurs($value, $primary)
{
    // ... my code here to retrieve the list of the authors in the database
    return $liste_auteurs;
}   

The problem with replacing a set_relation_n_n declaration by a callback, is that the "auteurs" field would not be diplayed in the list (i.e. columns) of the Å“uvres. One solution is to add a callback for the columns. The drawback is that you cannot sort the data by clicking the column title.

 

public function oeuvre()
{    
    $crud = new grocery_CRUD();
    $crud->set_table('oeuvre');
    
    // Do not declare the read-only field by a set_relation_n_n
    /// $crud->set_relation_n_n('auteurs', 'ecrit_oeuvre', 'personne', 'id_oeuvre', 'id_personne', 'nom', 'ordre');
    // Two differents callback functions (callback_field_auteurs and callback_column_auteurs) are necessary  
    // meannig, you can't use the same callback_auteurs() function for both callbacks (see further explanation)
    /// $crud->callback_field('auteurs',array($this,'callback_auteurs'));
    /// $crud->callback_column('auteurs',array($this,'callback_auteurs'));
    $crud->callback_field('auteurs',array($this,'callback_field_auteurs'));
    $crud->callback_column('auteurs',array($this,'callback_column_auteurs'));
    // Explicitly declare the read-only form field (note that this field has no equivalent in the database table, its only an HTML form field)
    // in the contrary, the 'titre' HTML field is linked to a field in the 'oeuvre' MySQL table
    // In this example, the read-only field is 'auteurs', 'titre' and 'descriptif' are the table 'oeuvre' fields
    // Since GroceryCrud has no function to add only a new HTML field, you have to explicitely declare all the displayed fields with the fields() and columns() functions  
    $crud->fields('titre','descriptif','auteurs');
    $crud->columns('titre','descriptif','auteurs');
    $output = $crud->render();
    $this->_prelib_output($output);        
}       

// As explained in the examples of the callback_field() and the callback_column() functions, http://www.grocerycrud.com/documentation/options_functions/callback_column and
// http://www.grocerycrud.com/documentation/options_functions/callback_column
// the callback functions for the field and the column have not the same parameters.
// As they share the same code in common, callback_column_auteurs() only calls callback_field_auteurs() with
// the appropriate parameters ...
// Also notice that $row and $primary concern 'oeuvre', not 'auteur' ($primary contains id_oeuvre, not id_auteur).  
function callback_column_auteurs($value, $row)
{    
    return $this->callback_field_auteurs($value, $row->id_oeuvre);
}    

function callback_field_auteurs($value, $primary)
{
    // ... my code here to retrieve the list of the authors in the database
    return $liste_auteurs;
}   
 

davidoster

davidoster
  • profile picture
  • Member

Posted 19 March 2013 - 15:21 PM

Now I understand better what you were trying to do.

Well the best solution to all this is not to use the set_relation_n_n function and try to solve it with your own model code.

This is what I do do in very difficult situations where I need something out of the ordinary, like make a field (that is used withing a set_relation function) as read only.