Modify multiple columns based on one value

Modify multiple columns based on one value

SWATswatSWATswat Posts: 109Questions: 0Answers: 0
edited June 28 in Editor

I have three tables:

TABLE entrepots :
id_entrepots int(200) NOT NULL,
nom_entrepots varchar(150) NOT NULL,

TABLE equipements :
nom_equipements varchar(200) NOT NULL,
groupe_equipements varchar(200) NOT NULL,
periodicite_equipements varchar(100) NOT NULL

TABLE controles :
id_controles int(200) NOT NULL,
date_controles_realiser date NOT NULL,
date_prochain_controles date NOT NULL,
date_rdv date NOT NULL,
etat_controles varchar(10) NOT NULL,

With the right leftovers to make it all work.

My problem:
When I open the modal to edit the data, I want to update several columns after modifying the date_controles_realiser.
example
date_controles_realiser in database is 2023-06-12
If I change it to 2024-06-12 and click on UPDATE :
Datatable will then display the new date in date_prochain_controles according to the data in the periodicite_equipements column (Annual, monthly, half-yearly, ...).
EX: if it's Annual, the new date date_prochain_controles will be 2024-06-12 and etat_controles will be "GREEN" if date_controles_realiser is less than or equal to the current date AND the date_rdv will be empty.

But I have no idea how to implement this Datatable Editor (version 1.9)

my code :

var editor; // use a global for the submit and return data rendering in the examples


    // Activate an inline edit on click of a table cell
    $('#example').on( 'click', 'tbody td.editable', function (e) {
        editor.inline( this, {
            //onBlur: 'submit'
            buttons: {  label: ">",
                        className: 'btn-sm',            
                        fn: function () { this.submit(); } }
        } );
    } );
    
    
    $('#example').DataTable( {
        initComplete: function () {
            this.api().columns([1,2,3,4,5,13]).every( function () {
                var column = this;
                var select = $('<select><option value="">ALL</option></select>')
                    .appendTo( $(column.footer()).empty() )
                    .on( 'change', function () {
                        var val = $.fn.dataTable.util.escapeRegex(
                            $(this).val()
                        );
 
                        column
                            .search( val ? ''+val+'' : '', true, false )
                            .draw();
                    } );
 
                column.data().unique().sort().each( function ( d, j ) {
                    select.append( '<option value="'+d+'">'+d+'</option>' )
                } );
            } );
        },
        dom: "Bfrtip",
        ajax: {
            url: "Staff_4.php",
            type: 'POST'
        },
        serverSide: false,
        columns: [
            {
                data: null,
                defaultContent: '',
                className: 'select-checkbox',
                orderable: false,
                searchable: false
            },
            
            { data: "controles.etat_controles", className: "dt-body-center" , 
                    target: [1],
                    type: "alt-string",
                    render: function ( data, type, row ) {
                      
                      if (type !== 'display') {
                        return data;
                      }
                      const icons = {
                        "BLANC": '<img src="img/blanc.gif" width="34" height="18" alt="BLANC" title="BLANC"/>',
                        "NOIR": '<img src="img/noir.gif" width="34" height="18" alt="NOIR" title="NOIR"/>',
                        "VERT": '<img src="img/vert.gif" width="34" height="18" alt="VERT" title="VERT"/>',
                        "ORANGE": '<img src="img/orange.gif" width="34" height="18" alt="ORANGE" title="ORANGE"/>',
                        "ROUGE": '<img src="img/rouge.gif" width="34" height="18" alt="ROUGE" title="ROUGE"/>',
                        "BLEU": '<img src="img/bleu.gif" width="34" height="18" alt="BLEU" title="BLEU"/>',
                      };

                      const values = data.split(', ');
                      let result = '';
                      values.forEach((value) => {
                        if (value.trim() in icons) {
                          result += icons[value.trim()];

                        } else {
                          result += value.trim();

                        }
                        result += ' '; // add space between values
                      });

                      return result.trim(); // remove extra space at the end

                    }
            
            },
            { data: "entrepots.nom_entrepots", editField: "controles.fk_entrepots", className: "dt-body-left", searchable: true },
            { data: "equipements.nom_equipements", editField: "controles.fk_equipements", className: "dt-body-left", searchable: true },
            { data: "equipements.groupe_equipements", className: "editable dt-body-center" },
            { data: "equipements.periodicite_equipements", className: "editable dt-body-center" },
            { data: "controles.date_controles_realiser", className: "editable dt-body-center" },
            { data: "controles.date_prochain_controles", className: "editable dt-body-center" },
            { data: "controles.date_rdv", className: "editable dt-body-center" },
            { data: "controles.commentaire", className: "dt-body-center"},
            { data: "controles.lien_fichier1", className: "dt-center",
            
                render: function ( data, type, row, meta ) {
                    if (data.startsWith('https://')){
                        return '<a href="'+data+'" target="_blank"><i class="fa fa-cloud" style="font-size:30px;color:lightgreen;text-shadow:2px 2px 4px #000000;" /></a>';     
                    }else{return data;} 
                }
            
            },
            { data: "controles.lien_fichier2", className: "dt-body-center", 
            
                render: function ( data, type, row, meta ) {
                    if (data.startsWith('https://')){
                        return '<a href="'+data+'" target="_blank"><i class="fa fa-cloud" style="font-size:30px;color:lightgreen;text-shadow:2px 2px 4px #000000;" /></a>';     
                    }else{return data;} 
                }
                
            },
            { data: "controles.lien_fichier3", className: "dt-body-center",
            
                render: function ( data, type, row, meta ) {
                    if (data.startsWith('https://')){
                        return '<a href="'+data+'" target="_blank"><i class="fa fa-cloud" style="font-size:30px;color:lightgreen;text-shadow:2px 2px 4px #000000;" /></a>';     
                    }else{return data;} 
                }   
            
            },
            { data: "controles.actif_controles", className: "dt-body-center" }
        ],
        order: [ 2, 'asc' ],
        select: {
            style:    'os',
            selector: 'td:first-child'
        },
        lengthMenu: [
            [ 10, 25, 50, -1 ],
            [ '10 rows', '25 rows', '50 rows', 'Show all' ]
        ],
        buttons: [
            { extend: 'create', editor: editor },
            { extend: 'edit',   editor: editor },
            { extend: 'remove',   editor: editor },
            {
                extend: 'collection',
                text: 'Export',
                buttons: [
                    'copy',
                    'excel',
                    'csv',
                    'pdf',
                    'print'
                ]
            },
            { extend: 'pageLength',   editor: editor }
        ]
    } );
} );

And server :

Editor::inst( $db, 'controles', 'id_controles' )
    ->field( 
        //Field::inst( 'controles.id_controles' ),
        Field::inst( 'controles.etat_controles' ),
        
        Field::inst( 'controles.fk_entrepots' )
            ->options( Options::inst()
                ->table( 'entrepots' )
                ->value( 'id_entrepots' )
                ->label( 'nom_entrepots' )
            )
            ->validator( Validate::dbValues() ),
        Field::inst( 'entrepots.nom_entrepots' ),
         
        Field::inst( 'controles.fk_equipements' )
            ->options( Options::inst()
                ->table( 'equipements' )
                ->value( 'id_equipements' )
                ->label( 'nom_equipements' )
            )
            ->validator( Validate::dbValues() ),
        Field::inst( 'equipements.nom_equipements' ),
        
        Field::inst( 'equipements.groupe_equipements' ),
        Field::inst( 'equipements.periodicite_equipements' ),
        Field::inst( 'controles.date_controles_realiser' )
            ->validator( Validate::dateFormat( 'Y-m-d' ) )
            ->getFormatter( Format::dateSqlToFormat( 'Y-m-d' ) )
            ->setFormatter( Format::dateFormatToSql('Y-m-d' ) )
            ->getFormatter( function ( $val, $data, $opts ) { 
                if ($val === "0000-00-00"){ echo ""; }else{ return date( 'Y-m-d', strtotime( $val ) ); } 
                } ),
        Field::inst( 'controles.date_prochain_controles' )
            ->validator( Validate::dateFormat( 'Y-m-d' ) )
            ->getFormatter( Format::dateSqlToFormat( 'Y-m-d' ) )
            ->setFormatter( Format::dateFormatToSql('Y-m-d' ) )
            ->getFormatter( function ( $val, $data, $opts ) { 
                if ($val === "0000-00-00"){ echo ""; }else{ return date( 'Y-m-d', strtotime( $val ) ); } 
                } ),
        Field::inst( 'controles.date_rdv' )
            ->validator( Validate::dateFormat( 'Y-m-d' ) )
            ->getFormatter( Format::dateSqlToFormat( 'Y-m-d' ) )
            ->setFormatter( Format::dateFormatToSql('Y-m-d' ) )
            ->getFormatter( function ( $val, $data, $opts ) { 
                if ($val === "0000-00-00"){ echo ""; }else{ return date( 'Y-m-d', strtotime( $val ) ); } 
                } ),
        Field::inst( 'controles.commentaire' ),
        Field::inst( 'controles.lien_fichier1' ),
        Field::inst( 'controles.lien_fichier2' ),
        Field::inst( 'controles.lien_fichier3' ),
        Field::inst( 'controles.actif_controles' )
        
    )
    
    ->leftJoin( 'entrepots', 'entrepots.id_entrepots', '=', 'controles.fk_entrepots' )
    ->leftJoin( 'equipements', 'equipements.id_equipements', '=', 'controles.fk_equipements' )
    ->debug(false)
    ->process($_POST)
    ->json();

thank you for your help as I don't know how to go about it

Replies

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin
    edited June 30

    Two options:

    1. Use dependent(). That is the method that is providied to update the form based on the input value of a field. You can set other field values, change visibility of fields and all that. This is the way to do it if the fields you want to modify are already available at the client-side.
    2. If the fields are not available at the client-side, use a server-side event - specifically preEdit and preCreate in this case. It can be used to set field values based on a function (i.e. your logic) which will then be written to the database.

    Allan

    edit Link correction

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421

    @allan used the French spelling here which doesn't take you anywhere in the docs. Here is the correct link:
    https://editor.datatables.net/reference/api/dependent()

    I think the documentation of "dependent" is very abstract and not that helpful. It took me years to really understand "dependent" and be able to use it effectively.

    In your case you could do something like this:

    editor
        .dependent('yourDateField', function (val, data, callback) {
            if (val > whatever) {
                this.set({'field2': 0, 'field3': "whatever"})
            }
            if (val > whatever) {
                this.show(['field2', 'field3']);
            } else {
                this.hide(['field2', 'field3']);
            }
            callback({});
        })
    

    If you need an example for server-side manipulation of submitted data: I have plenty of examples for that as well.

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin

    Doh! Thanks for catching @rf1234! I agree, the dependent() docs are not my finest. I've been thinking I need to have a whole section in the examples dedicated to showing what it can do. Or at the very least link to running live examples from the docs about each point.

    Great example - thank you.

    Allan

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421

    whole section in the examples dedicated to showing what it can do

    That would be great because it is really a lot, Allan.

  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Hello Allan, rf1234,

    Thank you very much for your answers.
    I'm going to look at/learn the dependent() side but I don't know javascript at all.
    Would you happen to have an online example?
    One question though, how do I transform my PHP functions into javascript?
    I know it's a lot to ask, but it would help me so much to understand.

    function DateProchainControlesMaj($actif_controles, $date_controles_realiser)
        {
            $today = date("Y-m-d");
            
            if ($actif_controles =="ON" && $date_controles_realiser <= $today){
                $annee = substr($date_controles_realiser,0,4);
                $mois = substr($date_controles_realiser,5,2);
                $jour = substr($date_controles_realiser,8,2);
                
                if ($periodicite_equipements=="Decenale"){
                    $DateProchainControles=date("Y-m-d", MKTIME(0,0,0, $mois, $jour, $annee + 10));
                }
                    if ($periodicite_equipements=="Sexennale"){
                        $DateProchainControles=date("Y-m-d", MKTIME(0,0,0, $mois, $jour, $annee + 6));
                    }
                        if ($periodicite_equipements=="Quinquenale"){
                            $DateProchainControles=date("Y-m-d", MKTIME(0,0,0, $mois, $jour, $annee + 5));
                        }
                            if ($periodicite_equipements=="Annuelle"){
                                $DateProchainControles=date("Y-m-d", MKTIME(0,0,0, $mois, $jour, $annee + 1));
                            }
                                if ($periodicite_equipements=="Semestrielle"){
                                    $DateProchainControles=date("Y-m-d", MKTIME(0,0,0, $mois + 6, $jour, $annee));
                                }
                                    if ($periodicite_equipements=="Trimestrielle"){
                                        $DateProchainControles=date("Y-m-d", MKTIME(0,0,0, $mois + 3, $jour, $annee));
                                    }
                                        if ($periodicite_equipements=="Mensuelle"){
                                            $DateProchainControles=date("Y-m-d", MKTIME(0,0,0, $mois + 1, $jour, $annee));
                                        }
                                            if ($periodicite_equipements=="Hebdomadaire"){
                                                $DateProchainControles=date("Y-m-d", MKTIME(0,0,0, $mois, $jour + 7, $annee));
                                            }
            }                                                   
            return  $DateProchainControles;                                         
        }   
    
    
    function etat_controlesMaj($actif_controles, $date_controles_realiser, $DateProchainControles)
        {
            $today = date("Y-m-d");
                
            if ($actif_controles =="ON"  )
            {
                    
                if ($date_controles_realiser <= $today && $DateProchainControles > $date_controles_realiser)  
                {  
                    if ($DateProchainControles > $today)
                    {
                        $etat_controles = "green.gif";
                    }
                    else 
                    {
                        $etat_controles = "black.gif";
                    }
                }
                
                if ($DateProchainControles == $today) 
                {
                    $etat_controles = "red.gif";
                }
            }
            else 
            {
                $etat_controles = "blue.gif";
                
            }
            return $etat_controles;
        }
            
    function date_rdvMaj($actif_controles, $date_controles_realiser, $DateProchainControles, $etat_controles)
        {       
            $today = date("Y-m-d");
            if ($actif_controles == "ON" && $date_controles_realiser <= $today && $DateProchainControles > $date_controles_realiser && $etat_controles =="green.gif") 
            {
                $date_rdv = "0000-00-00";
            }
            
            return $date_rdv;
        }
    

    Thank you in advance for taking the time to help me.

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421

    Why would you want to transform your PHP functions into Javascript? Are they supposed to run in the browser now?

  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Good question rf1234! Thanks. it's because I don't master dependent() at all and even less javascript. :)
    To try to understand dependent() in a global way
    When the user selects a table row and clicks on Edit, the Modal window opens.
    The user modifies the date date_controles_realiser and clicks on Update.
    The line information is sent to the server, intercepted by dependent() and the data is modified by my PHP functions, then after the fields have been modified, everything is sent to the database.
    Is this how it works or am I missing something? :)
    thank you for your help.

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421
    edited July 1

    "dependent" is executed when you open an Editor on the client side and also if you make changes to the relevant fields BEFORE any kind of server submission, regardless of what happens on the server. "dependent" also works if your data table isn't ajax sourced at all. So forget the server for a moment.

    Once you click "save" you send the data to the server in your case. By that time "dependent" will have been executed. There are mutliple event handlers that you can use with Editor.

    For example you can use "submitSuccess" if you want to do something after a successfull server submission. Or you can use "initSubmit" if you want to manipulate the Editor form prior to submission. You can also use "preSubmit" if you want to manipulate the data that will be send to the server after they have been read from the Editor form etc. etc.

    Here is an overview of the Editor events client side:
    https://editor.datatables.net/manual/events#Event-sequence

    And the overview of the editor events server side:
    https://editor.datatables.net/manual/php/events

    On the server side you can use your PHP scripts and manipulate data saved to your database, read from your database and whatever. For all of this you can use specific server events as described in the docs above.

    I will post a few examples from my coding below.

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421

    Front end example "dependent". This is a complex one where I create a dependency on three different fields at the same time. Setting, showing or hiding fields depending on the situation. When any of the three different fields are a) initially shown in the form, or b) change later on, the "dependent" code is being executed - regardless of what happens on the server.

    editor
        .dependent(['ctr.legal_basis', 'ctr.competitive', 'ctr.VAT_exempt'], function ( val, data, callback ) {
            //"competitive" only relevant for contracts under public law 
            // legal basis: 0 = no reply, 1 = civil law, 2 = public law
            if (this.val('ctr.legal_basis') == '2') {            
                this.show( ['ctr.competitive'] );
            } else {
                this.set( { 'ctr.competitive': 0 } )
                    .hide( ['ctr.competitive'] );
            }
            if (this.val('ctr.competitive') == '1' ||
                this.val('ctr.legal_basis') == '1'    ) {        
                this.show( ['ctr.VAT_exempt'] );
            } else {
                this.set( { 'ctr.VAT_exempt': 0 } )
                    .hide( ['ctr.VAT_exempt'] );
            }
            if (this.val('ctr.competitive') == '1' && this.val('ctr.VAT_exempt') == '0' ) {
                this.show( ['ctr.revenue_over_threshold'] );
            } else {
                this.set( { 'ctr.revenue_over_threshold': 0 } )
                    .hide( ['ctr.revenue_over_threshold'] );
            }
            callback({});
        })
    

    Another one: Do some weird stuff to prevent the user from deleting departments for which the user only has reading rights before server submission

    editor
        .on( 'preSubmit', function( e, d, action ) {
            if ( action === "edit" ) {
                if ( typeof d.data !== 'undefined' ) {
            //make sure that departments for which the user has only reading rights
            //cannot be deleted by the user!
            //reasons for having only reading rights for departments in the options dropdown:
            //a) the user has no rights for the department at all or has reading rights
            //   because the department was added by a different user, or
            //b) the user has deselected the department himself and it had been added before
                    var opts = $.extend(true, [], ctrGovdeptOptions);
                //  var deptsReadOnlyArray = [ {id: "123"}, {id: "234"}, {id: "22"} ];
                    var deptsReadOnlyArray = $.grep(opts, function(obj) {
                        return obj.editor < 1; //only depts where the user only has reading rights!
                    });
                    if ( deptsReadOnlyArray.length > 0 ) {
                        //get rid of unrequired attributes and rename "value" to "id"
                        deptsReadOnlyArray.forEach( function(data) {
                            data['id'] = data['value'];
                            delete data['value'];
                            delete data['label'];
                            delete data['editor'];
                        });
                        var key = Object.keys(d.data)[0];
                        d.data[key].ctr_govdept.push.apply(d.data[key].ctr_govdept, deptsReadOnlyArray);
                        d.data[key].ctr_govdept = removeDuplicatesArrayOfObjects(d.data[key].ctr_govdept);
                    }
                }
            }
        })
    

    Now server side:
    Add a summation line to the data returned from the server by Editor after reading the data from the database:

    ->on( 'postGet', function ( $e, &$data, $id ) use ( $lang ) { 
        if ( count($data) <= 0 ) {
            return;
        }
        $sum = array_sum(array_column($data, "unformattedAmount"));
        $keys = array_keys($data);
        foreach ( $keys as $key ) {
            unset($data[$key]["unformattedAmount"]);
        }
        if ( $sum != 0 ) {
            $data[] = [ "DT_RowId" => "row_0", //in reality there is no row 0 because it is derived from the SQL id
                        "sub_earmark" => 
                            [ "ctr_id"           => $_POST['ctr_id'], 
                              "earmark_subject"  => "",
                              "earmark_exp_date" => $lang === "de" ? "Summe" : "Total",
                              "earmark_amount"   => getFormatterAmount($sum) ] ];
        }
    })
    

    Write the log after creating, editing or removing records:

    ->on( 'postCreate', function ( $editor, $id, $values, $row ) {            
        logChange( $editor->db(), 'create', $id, $row, 'sub_earmark' );
    } )
    ->on( 'postEdit', function ( $editor, $id, $values, $row ) {
        logChange( $editor->db(), 'edit', $id, $row, 'sub_earmark' );
    } )
    ->on( 'postRemove', function ( $editor, $id, $values ) {
        logChange( $editor->db(), 'delete', $id, $values, 'sub_earmark' );
    } )
    

    You'll find plenty of examples in the docs, too! Good luck!

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421
  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Thank you very much for your feedback and for all this information and especially for the time you're devoting to my subject.
    I'm going to look at this carefully but I doubt I'll have the necessary level to understand it all.
    I'd already seen the last example quoted above, but I'm wondering if it really corresponds to what I want to do, i.e. modify the data (column) of a row after modifying a data (column) of this same row just after the update but before writing to the database.

    According to the link you've given me, I'm wondering if I shouldn't use writeEdit to modify the 3 fields in my row after the user has changed the date during an Update?

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421
    edited July 1

    modify the data (column) of a row after modifying a data (column) of this same row just after the update but before writing to the database.

    The easiest way for this is "dependent" on the client side, I guess.

    editor
        .dependent('column1', function (val, data, callback) {
            if (val == "whatever") {
                this.set({'column2': "whatever")
            }
            callback({});
        })
    

    If you just wanted to set column2 to the value of column1 it would be even easier.

    editor
        .dependent('column1', function (val, data, callback) {
            this.set({'column2': val});
            callback({});
        })
    

    for three fields

    editor
        .dependent('column1', function (val, data, callback) {
            this.set({'column2': val, 'column3': val, 'column4': val});
            callback({});
        })
    

    Server side solution:
    You would NOT want to use "writeEdit" because then the incomplete data has already been written to the database. What you would want to use instead is "preEdit" or "validatedEdit".

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421

    On a personal note: I started with JS, jQuery and PHP in 2016. Before that I only knew Cobol, Pascal and SQL - and my last commercial coding experience had ended in 1997.
    No problem to learn Javascript or anything. It is just a programming language, not rocket science! Just take a couple of online classes. Udemy.com is pretty good for this.

    You should also familiarize yourself with the basic architecture: What runs in the browser? What runs on the server and why? And how does all of that stuff interact? There is plenty of training materials out there. Good luck!

  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Ok for this one, because I don't need the other one because no column value replaces another.

    editor
        .dependent('column1', function (val, data, callback) {
            if (val == "whatever") {
                this.set({'column2': "whatever")
            }
            callback({});
        })
        
    

    if I begin to understand and with my information :

    editor
        .dependent('date_controles_realiser', function (val, data, callback) {
            var ToDay = now();
            var periodiciteEquipements = val['periodicite_equipements'];
            var dateRdv = val['date_rdv'];
            var etatControles = val['etat_controles'];
            
            if (val == "???") {
            
                this.set({'date_controles_realiser': "MY_RESULT")
            }
            
            callback({});
        })
        
    

    date_controles_realiser this is the field that will be modified by the user.
    I retrieve the current date,
    I retrieve the periodicity to determine the future date,
    I retrieve the appointment date for the control,
    and I retrieve the status of my line.

    In the IF, I do all my checks to find MY_RESULT,

    and in this.set({'date_controles_realiser': "MON_RESULTAT") I send my result

    I don't think it's fair the way it's written, but is the process going in the right direction?

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421
    edited July 1
    editor
        .dependent('date_controles_realiser', function (val, data, callback) {
            var ToDay = now();
            var periodiciteEquipements = val['periodicite_equipements'];
            var dateRdv = val['date_rdv'];
            var etatControles = val['etat_controles'];
             
            if (val == "???") {
             
                this.set({'date_controles_realiser': "MY_RESULT")
            }
             
            callback({});
        })
    

    "val" is the value of the variable you are looking at. In this case it is 'date_controles_realise'. So val['periodicite_equipements'] doesn't work.
    You need to get an Editor value instead.

    editor
        .dependent('date_controles_realiser', function (val, data, callback) {
            var ToDay = new Date(); // you will need to transform this to your format
            var periodiciteEquipements = this.val('periodicite_equipements');
            var dateRdv = this.val('date_rdv');
            var etatControles = this.val('etat_controles');
             
            if (val == "???") { //this is the value of date_controles_realiser
             
                this.set({'date_controles_realiser': "MY_RESULT"})
            }
             
            callback({});
        })
    
  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Thanks a lot, it's becoming clearer and thanks also for the training info. I'll seriously think about it.
    I'll make progress on the verification conditions and post if I run into any difficulties, thanks again.

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421
    edited July 1

    Regarding the date: This is a bit odd in JS. Hence many people use plugins like moment.js etc.

    I coded this a long time ago to make the date transformation to something more useful for today's date ... So if you are not using a plugin you might find this useful.

    var currentTime = new Date();
    var pad = '00';
    
    var hlp = currentTime.getMonth() + 1;
    hlp = hlp.toString();
    var month = pad.substr(0, pad.length - hlp.length) + hlp;
    
    hlp = currentTime.getDate().toString();
    var day = pad.substr(0, pad.length - hlp.length) + hlp;
    
    var year = currentTime.getFullYear().toString();
    
    var MMDDYYYY = month + day + year;
    

    So MMDDYYYY would be 07012024 right now and
    day+ '/' + month+ '/' + year
    would be 01/07/2024.

    I run this code initially when a page gets loaded and the variables are global variables. Hence I can use "MMDDYYYY", "month", "day" and "year" throughout all of my code without thinking about them.

    thanks also for the training info. I'll seriously think about it.

    This one got me jump started a couple of years ago. Great teacher!
    https://www.udemy.com/course/the-complete-web-developer-course-2/?couponCode=LETSLEARNNOWPP

  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Thanks rf1234 for this date example, but I work with dates in the English format YYYY-mm-dd.
    I'm going to look into training very seriously, but in the meantime, I really need to get this dependent() working.
    Here I am, a lot of fruitless search time to find out how to pass javascript variables to PHP.

    editor
    .dependent('date_controles_realiser', function (val, data, callback) {
            //var ToDay = new Date().toISOString().split('T')[0]; // you will need to transform this to your format
            var periodiciteEquipements = this.val['periodicite_equipements'];
            //var dateRdv = this.val['date_rdv'];
            var etatControles = this.val['etat_controles'];
            var actifControles = this.val['actif_controles'];
            var dateControlesRealiser = this.val['date_controles_realiser'];
          
                  ...
            <?php
            //On utilise les fonctions PHP pour récupérer les valeurs apres calcul
                $DateProchainControles = DateProchainControlesMaj($actifControles, $dateControlesRealiser, $periodiciteEquipements);
                $NewEtatControle = etat_controlesMaj($actifControles, $dateControlesRealiser, $DateProchainControles);
                $NewDateRdv = date_rdvMaj($actifControles, $dateControlesRealiser, $DateProchainControles, $NewEtatControle);
            ?>
    
    
            
           if (val != "") {
              
                this.set({'date_prochain_controles': "<?PHP echo $DateProchainControles; ?>", 'etat_controles': "<?PHP echo $NewEtatControle; ?>", 'date_rdv': "<?PHP echo $NewDateRdv; ?>"});
            }
              
            callback({});
        });
    

    That's why I was thinking of converting my PHP functions to Javascript.
    But in both cases I can't find it.
    I'm continuing my research into adapting PHP functions to javascript.

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421

    but I work with dates in the English format YYYY-mm-dd.

    That would be

    year + '-' + month + '-' + day
    

    using my code posted above.

    <?php
            //On utilise les fonctions PHP pour récupérer les valeurs apres calcul
                $DateProchainControles = DateProchainControlesMaj($actifControles, $dateControlesRealiser, $periodiciteEquipements);
                $NewEtatControle = etat_controlesMaj($actifControles, $dateControlesRealiser, $DateProchainControles);
                $NewDateRdv = date_rdvMaj($actifControles, $dateControlesRealiser, $DateProchainControles, $NewEtatControle);
            ?>
    

    If you need to retrieve values from the server in your "dependent" statement you can not simply embed php code. You need to make an ajax call to the server and get the information from there.

    Here is a very old example from my own coding:

    contractEditor
        .dependent('contract.govdept_id', function (val, data, callback) {
            if (val > '0' && data.values['contract.iban'] <= '') {
                $.ajax({
                    type: "POST",
                    url: 'actions.php?action=getIban',
                    data: {govdeptId: val},
                    dataType: "json",
                    success: function (data) {
                        contractEditor.set({'contract.iban': data.iban});
                        callback({});
                    }
                });
            } else {
                callback({});
            }
        })
    

    I am getting the default IBAN of a department if it isn't filled yet in the contract data. Ajax calls are asynchronous by default. Hence I can only set the field "contract.iban" once the call will have been completed.

    Take a look at the "url": I call a server script that gets the IBAN for me and returns it to the client.

    This code is part of "actions.php". Based on the value of the get variable it calls a script "getIban" that retrieves the IBAN from the database and returns the value to the client.

    switch ($getVariable) {
        case "getIban":
            echo json_encode( getIban(filter_input(INPUT_POST,'govdeptId'), $dbh) );
            break;
    

    P.S.: I learned all of this in the class I recommended above ... You will need training - even for this seemingly "simple" task, I am afraid.

  • rf1234rf1234 Posts: 2,996Questions: 87Answers: 421

    In the meantime of course there are alternatives to ajax calls. You could also use this for example:
    https://medium.com/@sagarkumar2499/best-alternatives-to-ajax-dee210d71ed7#:~:text=Fetch%20API%3A%20The%20Fetch%20API,interface%20for%20making%20network%20requests.

    I personally stick to jQuery and ajax-calls. Why change a winning team? :smile:

  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Hello rf1234,

    Thank you for all this information, I'm going to have a good look at it while I'm on holiday and I'll come back to post if I get stuck somewhere.
    Thanks again for your help.

  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Hello,

    Ma dependent code :


    editor .dependent(['controles.etat_controles', 'controles.actif_controles', 'controles.date_controles_realiser', 'equipements.periodicite_equipements'], function (val, data, callback) { var toDay1 = new Date(); var periodiciteEquipements = this.val['equipements.periodicite_equipements']; //var dateRdv = this.val['date_rdv']; var etatControles = this.val['controles.etat_controles']; var actifControles = this.val['controles.actif_controles']; var dateControlesRealiser = this.val['controles.date_controles_realiser']; var dateProchainControle =""; var dateRendezVous=""; //1 : si actifControles est egale a ON on traite if (actifControles === "ON" && etatControles !== "VERT") { //2 : calcule de dateProchainControles par rapport à periodiciteEquipements et dateControlesRealiser via fonction DateProchainControle = DateProchainControlesMaj(dateControlesRealiser, periodiciteEquipements); //3 MàJ etatControles == GREEN si dateProchainControles > dateControlesRealiser var MadateControlesRealiser = new Date(dateControlesRealiser); var MaDateProchainControles = new Date(DateProchainControle); if(MadateControlesRealiser.getTime() <= toDay1.getTime() && MaDateProchainControles.getTime() > MadateControlesRealiser) { if(MaDateProchainControles.getTime() > toDay1.getTime()) { etatControles = "VERT"; dateRendezVous = "0000-00-00"; } else { etatControles = "NOIR"; } } } if (val !== "") { this.set({'DateProchainControles': dateProchainControle}), this.set({'etat_controles': etatControles}), this.set({'date_rdv': dateRendezVous}) } callback({}); });

    I don't know if what I've written is correct, but it doesn't work. I think it's my need to query fields on 2 tables that's blocking it.

    If you have an idea, I'd appreciate it.

    Thanks

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin

    It looks like it should set the value for three fields. If you'd like me to take a look at it, can you link to a page showing the issue so I can use a debugger on it and hopefully offer some help.

    Allan

  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Hello Allan,

    The link is in private message.

    Thank you very much for your precious help.

  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0

    Hello,

    After following Allan's advice (whom I thank),
    I upgraded datatable 1.9 to 2.0.
    I changed “this.val[]” to “this.val()”.
    As a result, “this.val()” now works.
    The problem I'm having now is with my “DateProchainControlesMaj()” function, which works only with manually entered variables, but doesn't work in datatables, and I don't understand why.
    here's the code for my page:

    function DateProchainControlesMaj (MaDate, MaPeriode) {
        var periodicite = MaPeriode;
        var maNewDate=new Date(MaDate);
        var thisYear="";
        var plusAnnee="";
        var DansXAns="";
        var thisMonth="";
        var plusMois="";
        var DansXMois="";
        var thisDay="";
        var plusJour="";
        var DansXJours="";
        var MonResultat="";
            if(periodicite === "Decenale")
        {
            thisYear = maNewDate.getUTCFullYear();
            plusAnnee=10;
            DansXAns=new Date(maNewDate);
            DansXAns.setUTCFullYear(thisYear+plusAnnee);
            MonResultat = DansXAns.toLocaleDateString('en-CA');
    
        }
        if(periodicite === "Sexennale"){
            thisYear = maNewDate.getUTCFullYear();
            plusAnnee=6;
            DansXAns=new Date(maNewDate);
            DansXAns.setUTCFullYear(thisYear+plusAnnee);
            MonResultat = DansXAns.toLocaleDateString('en-CA');
        }
        if(periodicite === "Quinquenale"){
            thisYear = maNewDate.getUTCFullYear();
            plusAnnee=5;
            DansXAns=new Date(maNewDate);
            DansXAns.setUTCFullYear(thisYear+plusAnnee);
            MonResultat = DansXAns.toLocaleDateString('en-CA');
        }
        if(periodicite === "Annuelle"){
            thisYear = maNewDate.getUTCFullYear();
            plusAnnee=1;
            DansXAns=new Date(maNewDate);
            DansXAns.setUTCFullYear(thisYear+plusAnnee);
            MonResultat = DansXAns.toLocaleDateString('en-CA');
        }
        if(periodicite === "Semestrielle"){
            thisMonth = maNewDate.getUTCMonth();
            plusMois=6; 
            DansXMois=new Date(maNewDate);
            DansXMois.setUTCMonth(thisMonth+plusMois);
            MonResultat = DansXMois.toLocaleDateString('en-CA');
        }
        if(periodicite === "Trimestrielle"){
            thisMonth = maNewDate.getUTCMonth();
            plusMois=3; 
            DansXMois=new Date(maNewDate);
            DansXMois.setUTCMonth(thisMonth+plusMois);
            MonResultat = DansXMois.toLocaleDateString('en-CA');
        }
        if(periodicite === "Mensuelle"){
            thisMonth = maNewDate.getUTCMonth();
            plusMois=1;  
            DansXMois=new Date(maNewDate);
            DansXMois.setUTCMonth(thisMonth+plusMois);
            MonResultat = DansXMois.toLocaleDateString('en-CA');
        }
        if(periodicite === "Hebdomadaire"){
            thisDay = maNewDate.getUTCDate();
            plusJour=7;
            DansXJours=new Date(maNewDate);
            DansXJours.setUTCDate(thisDay+plusJour);
            MonResultat = DansXJours.toLocaleDateString('en-CA');
        }
        return MonResultat;
    };  
    
    var editor; // use a global for the submit and return data rendering in the examples
    
    $(document).ready(function() {
        editor = new $.fn.dataTable.Editor( {
            
            ajax: "Staff_4.php",
            table: "#example",
            display: "bootstrap",
            fields: [ {
                    label: "etat_controles :",
                    name: "controles.etat_controles",
                    type: "readonly"
                }, {
                    label: "date_controles_realiser :",
                    name: "controles.date_controles_realiser",
                    type: "datetime"
                }, {
                    label: "date_prochain_controles :",
                    name: "controles.date_prochain_controles",
                    type: "readonly"
                }, {
                    label: "date_rdv :",
                    name: "controles.date_rdv",
                    type: "datetime"
                }, {
                    label: "commentaire :",
                    name: "controles.commentaire",
                    type:  "textarea"
                }, {
                    label: "lien_fichier1 :",
                    name: "controles.lien_fichier1"
                }, {
                    label: "lien_fichier2 :",
                    name: "controles.lien_fichier2"
                }, {
                    label: "lien_fichier3 :",
                    name: "controles.lien_fichier3"
                }, {
                    label: "actif_controles :",
                    name: "controles.actif_controles"
                }, {
                    label: "périodicité :",
                    name: "equipements.periodicite_equipements",
                    type: "readonly"
                }
            ]
        } );
    
        // Activate an inline edit on click of a table cell
        $('#example').on( 'click', 'tbody td.editable', function (e) {
            editor.inline( this, {
                //onBlur: 'submit'
                buttons: {  label: "&gt;",
                            className: 'btn-sm',            
                            fn: function () { this.submit(); } }
            } );
        } );
        
        editor.dependent(['controles.etat_controles', 'controles.actif_controles', 'controles.date_controles_realiser', 'equipements.periodicite_equipements'], function (val, data, callback) {
            
            var toDay1 = new Date();
            var periodiciteEquipements = this.val('equipements.periodicite_equipements');
            //var dateRdv = this.val('date_rdv');
            var etatControles = this.val('controles.etat_controles');
            var actifControles = this.val('controles.actif_controles');
            var dateControlesRealiser = this.val('controles.date_controles_realiser');
            var dateProchainControle ="";
            var dateRendezVous="";
            
            //1 : si actifControles est egale a ON on traite
            if (actifControles === "ON" && etatControles !== "VERT")
            {
                //2 : calcule de dateProchainControles par rapport à periodiciteEquipements et dateControlesRealiser via fonction
                
            DateProchainControle = DateProchainControlesMaj(dateControlesRealiser, periodiciteEquipements);
                    //3 MàJ etatControles == GREEN si dateProchainControles > dateControlesRealiser
                    var MadateControlesRealiser = new Date(dateControlesRealiser);
                    var MaDateProchainControles = new Date(DateProchainControle);
                                
                    if(MadateControlesRealiser.getTime() <= toDay1.getTime() && MaDateProchainControles.getTime() > MadateControlesRealiser.getTime())
                    {
                        if(MaDateProchainControles.getTime() > toDay1.getTime())
                        {
                            etatControles = "VERT";
                            dateRendezVous = "0000-00-00";
                    
                        }
                        else
                        {
                            etatControles = "NOIR";
                        }   
                    }   
            }
            
        if (val !== "") {
                //editor.field('controles.date_prochain_controles').set(dateProchainControle),
                //editor.field('controles.etat_controles').set(etatControles),
            //editor.field('controles.date_rdv').set(dateRendezVous),
            //this.set({'controles.date_prochain_controles': dateProchainControle}),
            //this.set({'controles.etat_controles': etatControles}),
            //this.set({'controles.date_rdv': dateRendezVous}),
            console.log("dateProchainControle : " +dateProchainControle),
                console.log("etatControles : " +etatControles),
            console.log("dateRendezVous : " +dateRendezVous),
            console.log("dateControlesRealiser : " +dateControlesRealiser),
            console.log("periodiciteEquipements : " +periodiciteEquipements)
                
            } 
            callback({});
        });
        
    $('#example').DataTable( {
            initComplete: function () {
                this.api().columns([1,2,3,4,5,13]).every( function () {
                    var column = this;
                    var select = $('<select><option value="">ALL</option></select>')
                        .appendTo( $(column.footer()).empty() )
                        .on( 'change', function () {
                            var val = $.fn.dataTable.util.escapeRegex(
                                $(this).val()
                            );
     
                            column
                                .search( val ? ''+val+'' : '', true, false )
                                .draw();
                        } );
     
                    column.data().unique().sort().each( function ( d, j ) {
                        select.append( '<option value="'+d+'">'+d+'</option>' )
                    } );
                } );
            },
            dom: "Bfrtip",
            ajax: {
                url: "Staff_4.php",
                type: 'POST'
            },
            serverSide: false,
            columns: [
                {
                    data: null,
                    defaultContent: '',
                    className: 'select-checkbox',
                    orderable: false,
                    searchable: false
                },
                
                { data: "controles.etat_controles", className: "dt-body-center" , 
                        target: [1],
                        type: "alt-string",
                        render: function ( data, type, row ) {
                          
                          if (type !== 'display') {
                            return data;
                          }
                          const icons = {
                            "BLANC": '<img src="img/blanc.gif" width="34" height="18" alt="BLANC" title="BLANC"/>',
                            "NOIR": '<img src="img/noir.gif" width="34" height="18" alt="NOIR" title="NOIR"/>',
                            "VERT": '<img src="img/vert.gif" width="34" height="18" alt="VERT" title="VERT"/>',
                            "ORANGE": '<img src="img/orange.gif" width="34" height="18" alt="ORANGE" title="ORANGE"/>',
                            "ROUGE": '<img src="img/rouge.gif" width="34" height="18" alt="ROUGE" title="ROUGE"/>',
                            "BLEU": '<img src="img/bleu.gif" width="34" height="18" alt="BLEU" title="BLEU"/>',
                          };
    
                          const values = data.split(', ');
                          let result = '';
                          values.forEach((value) => {
                            if (value.trim() in icons) {
                              result += icons[value.trim()];
    
                            } else {
                              result += value.trim();
    
                            }
                            result += ' '; // add space between values
                          });
    
                          return result.trim(); // remove extra space at the end
    
                        }
                
                },
                { data: "entrepots.nom_entrepots", editField: "controles.fk_entrepots", className: "dt-body-left", searchable: true },
                { data: "equipements.nom_equipements", editField: "controles.fk_equipements", className: "dt-body-left", searchable: true },
                { data: "equipements.groupe_equipements", className: "editable dt-body-center" },
                { data: "equipements.periodicite_equipements", className: "editable dt-body-center" },
                { data: "controles.date_controles_realiser", className: "editable dt-body-center" },
                { data: "controles.date_prochain_controles", className: "editable dt-body-center" },
                { data: "controles.date_rdv", className: "editable dt-body-center" },
     ...
        } );
    } );
    

    Here's what I've got in the console (which runs in a loop):

    dateProchainControle : 
    etatControles : VERT 
    dateRendezVous : 
    dateControlesRealiser : 2024-07-20 
    periodiciteEquipements : Annuelle
    

    Is the function correctly positioned?
    if so, what can prevent the “DateProchainControlesMaj()” function from working?

    Thanks for your help, I think I'm nearing the end.

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin
    if (actifControles === "ON" && etatControles !== "VERT")
    

    Is this condition being met? In the three rows in the example you sent me, all three rows have actifControles === "".

    It looks like you also has an infinite loop. editor.field('controles.etat_controles').set(etatControles) is inside the event handler for controles.etat_controles changing! So every time it sets, it will call itself.

    You may need to break that out into a different function. Or check the value of etatControles compared to the field's value at the moment, and only set if needed:

    if (editor.field('controles.etat_controles').get() !== etatControles) {
      editor.field('controles.etat_controles').set(etatControles);
    }
    

    Finally, I'm not sure about the syntax of using a comma to end the link for the setting of the field values:

                editor.field('controles.date_prochain_controles').set(dateProchainControle),
                editor.field('controles.etat_controles').set(etatControles),
                editor.field('controles.date_rdv').set(dateRendezVous),
    

    I'd suggest using a semi-colon.

    Allan

  • SWATswatSWATswat Posts: 109Questions: 0Answers: 0
    edited July 23

    Hello Allan,

    Thank you very much, everything is working fine now.
    I modified a silly error in the name of the function and the name of 2 variables then I followed your advice by putting :

    if (editor.field('controles.etat_controles').get() === etatControles){...}
    

    Here is the functional code of the depent :

    editor.dependent(['controles.etat_controles', 'controles.actif_controles', 'controles.date_controles_realiser', 'equipements.periodicite_equipements'], function (val, data, callback) {
            
            var toDay1 = new Date();
            var periodiciteEquipements = this.val('equipements.periodicite_equipements');
            //var dateRdv = this.val('date_rdv');
            var etatControles = this.val('controles.etat_controles');
            var actifControles = this.val('controles.actif_controles');
            var dateControlesRealiser = this.val('controles.date_controles_realiser');
            var dateProchainControle ="";
            var dateRendezVous="";
            
            
            //1 : si actifControles est egale a ON on traite
            if (actifControles === "ON" )
            {
                if (editor.field('controles.etat_controles').get() === etatControles) 
                {
     
                    //2 : calcule de dateProchainControles par rapport à periodiciteEquipements et dateControlesRealiser via fonction
                
                    dateProchainControle = dateProchainControlesMaj(dateControlesRealiser, periodiciteEquipements);
                    //3 MàJ etatControles == GREEN si dateProchainControles > dateControlesRealiser
                    var MadateControlesRealiser = new Date(dateControlesRealiser);
                    var MaDateProchainControles = new Date(dateProchainControle);
                                
                    if(MadateControlesRealiser.getTime() <= toDay1.getTime() && MaDateProchainControles.getTime() > MadateControlesRealiser.getTime())
                    {
                        if(MaDateProchainControles.getTime() > toDay1.getTime())
                        {
                            etatControles = "VERT";
                            dateRendezVous = "0000-00-00";
                    
                        }
                        else
                        {
                            etatControles = "NOIR";
                        }   
                    }
                
                
                }
                
            }
            
            if (val !== "") {
                this.set({'controles.date_prochain_controles': dateProchainControle});
                this.set({'controles.etat_controles': etatControles});
                this.set({'controles.date_rdv': dateRendezVous});
                
                
            } 
              
            callback({});
        });
    

    Thanks Allan and rf1234 for your time and help.

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin

    Awesome - great to hear you got it working :)

    Allan

Sign In or Register to comment.