Besoin d'aide ?

MISE EN PLACE D'UN TABLEAU DYNAMIQUE

  • Avatar de lavarelkyi
    Membre depuis :
    20/12/2017
    Messages :
    71

    Salut,

    $query=DB::table('matieres')
    ->join('notes','matieres.id','=','notes.matiere_id')
    ->join('eleves','notes.eleve_id','=','eleves.id')
    ->join('trimestres','notes.trimestre_id','=','trimestres.id')
    ->join('annees','trimestres.annee_id','=','annees.id')
    ->select('notes.note','eleves.nom','eleves.prenom','matieres.lib_mat','annees.lib_anne','trimestres.lib_trimestre','notes.dat_note')
    ->where('lib_trimestre','trimestre 1')
    ->Where('matricule',$matricule)
    ->get();

    La requête ci-dessus me permet d'afficher dans un tableau le nom, le prenom, la note, le libelle de la matières, année en cour, le trimestre et la date.
    Et moi j'aimerais pouvoir fusionner les noms des matières qui sont identiques, année en cour puisque l'année en cour est identique pour toutes les notes et les noms des trimestres.

    Je tiens à préciser egalement que l'affichage du tableau ce fais avec ajax,

    Voici un peu ce que j'ai pu realiser :

    ---------------------------------------------------- Mon Controller -----------------------------------------------------------

    public function RechercheMatricule(Request $request){

    $matricules = DB::table('eleves')
    ->select('id','nom','prenom')
    ->whereMatricule($request->matricule_eleve)
    ->first();

    $matricule_eleve_id = DB::table('inscriptions')
    ->select('eleve_id')
    ->whereEleveId($matricules->id)
    ->first();

    if($matricule_eleve_id==null)
    return response()->json([
    'fail'=>true,
    'errors'=>'<p>Aucun eleve ne correspond à ce matricule</p>'
    ]);
    else{
    $table = $this->RetourneTableauFiltre($request->matricule_eleve);
    return response()->json($table);
    }
    }
    //==============================================================================

    private function RetourneTableauFiltre($matricule){

    $query=DB::table('matieres')
    ->join('notes','matieres.id','=','notes.matiere_id')
    ->join('eleves','notes.eleve_id','=','eleves.id')
    ->join('trimestres','notes.trimestre_id','=','trimestres.id')
    ->join('annees','trimestres.annee_id','=','annees.id')
    ->select('notes.note','eleves.nom','eleves.prenom','matieres.lib_mat','annees.lib_anne','trimestres.lib_trimestre','notes.dat_note')
    ->where('lib_trimestre','trimestre 1')
    ->Where('matricule',$matricule)
    ->get();
    $table='';
    $boolean = true;
    foreach ($query as $builder) {
    $annee_en_cour = intVal($builder->lib_anne)+1;
    if($boolean){
    $table.='<tr>
    <td rowspan="'. $query->count() .'">'. $builder->nom .' '. $builder->prenom .'</td>
    <td>'. $builder->note.'/20' .'</td>
    <td>'. $builder->dat_note .'</td>
    <td rowspan="'. query_nombreMatiere($builder->lib_mat) .'">'. $builder->lib_mat .'</td>
    <td rowspan="'. $query->count() .'">'. $builder->lib_trimestre .'</td>
    <td rowspan="'. $query->count() .'">'. $builder->lib_anne.'-'. $annee_en_cour .'</td>
    </tr>';
    }elseif ((!$boolean)&&(query_nombreMatiere($builder->lib_mat)==1)) {
    $table.='<tr>
    <td>'. $builder->note .'/20' .'</td>
    <td>'. $builder->dat_note .'</td>
    <td>'. $builder->lib_mat .'</td>
    </tr>';
    }elseif ((!$boolean)&&(query_nombreMatiere($builder->lib_mat)>1)) {
    $table.='<tr>
    <td>'. $builder->note .'/20' .'</td>
    <td>'. $builder->dat_note .'</td>
    </tr>';
    }
    $boolean=false;
    }
    return $table;
    }

    N.B : (query_nombreMatiere()) est un fonction helper qui renvoi le nombre de chaque matiere dans qu'on lui transmet;

    -------------------------------------------------- Mon code Ajax -------------------------------------------------------------

    $(document).ready(function(){
    $(document).on('click','#recherchefiltre', function(e){
    $matricule_eleve = $('.matricule_inscription').val();
    if($matricule_eleve!=''){
    $('.tableaufiltre').removeAttr('hidden');
    $.ajax({
    method:'GET',
    url:'Recherche/filtre',
    Datatype:'JSON',
    data:{
    'matricule_eleve':$matricule_eleve
    }
    })
    .success(function(data){

    $('.tableNote').html(data);
    });
    }else{
    alert("Entré le matricule");
    }
    });
    });

    --------------------------------------------------- Et ma vue -------------------------------------------------------------------

    <div class="row clearfix tableaufiltre" hidden>
    <!-- Task Info 2 -->
    <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
    <div class="card">
    <div class="header">
    <h2>{{__('RECHERCHE')}}</h2>
    </div>
    <div class="body table-responsive">
    <table class="table table-bordered table-hover">
    <thead>
    <tr>
    <th>NOM ET PRENOM</th>
    <th>NOTES</th>
    <th>DATES NOTES</th>
    <th>MATIERES</th>
    <th>TRIMESTRES</th>
    <th>ANNEE SCOLAIRE</th>
    </tr>
    </thead>
    <tbody class="tableNote">
    </tbody>
    </table>
    </div>
    </div>
    </div>
    </div>

    Merci pour votre aide ...

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2178

    C'est pas facile de comprendre l'organisation des données...

  • Avatar de lavarelkyi
    Membre depuis :
    20/12/2017
    Messages :
    71

    Salut @bestmomo,

    Voici l'affichage normal du tableau avec ce code :

    foreach ($query as $builder) {
    $annee_en_cour = intVal($builder->lib_anne)+1;

    $table.='<tr>
    <td>'. $builder->nom .' '. $builder->prenom .'</td>
    <td>'. $builder->note.'/20' .'</td>
    <td>'. $builder->dat_note .'</td>
    <td>'. $builder->lib_mat .'</td>
    <td>'. $builder->lib_trimestre .'</td>
    <td>'. $builder->lib_anne.'-'. $annee_en_cour .'</td>
    </tr>';
    }
    return $table;
    }

    et voici une image de ce que cela donne :(https://imgur.com/a/c6UHV07)

    et moi j'aimerais pouvoir fusionner les colonnes identiques et ceux de manières dynamiques puisque le nombre de matiere peut evoluer à tous moment...

    Merci...

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2178

    Salut,

    Là j'ai compris mais pas si facile à réaliser...

    Pour essayer ça avec des données je suis parti d'une simple table :

    Schema::create('matieres', function(Blueprint $table) {
    $table->increments('id');
    $table->timestamps();
    $table->string('nom');
    $table->string('note');
    $table->timestamp('dat_note');
    $table->string('lib_mat');
    $table->string('lib_trimestre');
    $table->string('lib_annee');
    });

    Que j'ai nourrie avec 4 enregistrements pour arriver en gros à tes données :

    DB::table('matieres')->insert([
    'nom' => 'Emmanuel',
    'note' => '15/20',
    'dat_note'=> Carbon::today(),
    'lib_mat' => 'Maths',
    'lib_trimestre' => 'trimestre 1',
    'lib_annee' => '2018',
    ]);

    DB::table('matieres')->insert([
    'nom' => 'Emmanuel',
    'note' => '15/20',
    'dat_note'=> Carbon::yesterday(),
    'lib_mat' => 'Maths',
    'lib_trimestre' => 'trimestre 1',
    'lib_annee' => '2018',
    ]);

    DB::table('matieres')->insert([
    'nom' => 'Emmanuel',
    'note' => '12/20',
    'dat_note'=> Carbon::today()->subWeekdays(2),
    'lib_mat' => 'Maths',
    'lib_trimestre' => 'trimestre 1',
    'lib_annee' => '2018',
    ]);

    DB::table('matieres')->insert([
    'nom' => 'Emmanuel',
    'note' => '12/20',
    'dat_note'=> Carbon::today()->subWeekdays(3),
    'lib_mat' => 'Anglais',
    'lib_trimestre' => 'trimestre 1',
    'lib_annee' => '2018',
    ]);

    Sans traitement spécifique ça donne ça.

    J'ai créé cette vue :

    <style>
    table, th, td {
    border: 1px solid black;
    border-collapse: collapse;
    }
    </style>

    <table>
    <tr>
    <th>Nom</th>
    <th>Notes</th>
    <th>Date notes</th>
    <th>Matières</th>
    <th>Trimestres</th>
    <th>Années</th>
    </tr>
    @php
    $index = 0;
    @endphp
    @foreach ($matieres as $matiere)
    <tr>
    @if($rowspans[$index] > 0)
    <th rowspan="{{ $rowspans[$index++] }}">{{ $matiere->nom }}</th>
    @else @php ++$index; @endphp
    @endif
    @if($rowspans[$index] > 0)
    <th rowspan="{{ $rowspans[$index++] }}">{{ $matiere->note }}</th>
    @else @php ++$index; @endphp
    @endif
    @if($rowspans[$index] > 0)
    <th rowspan="{{ $rowspans[$index++] }}">{{ $matiere->dat_note }}</th>
    @else @php ++$index; @endphp
    @endif
    @if($rowspans[$index] > 0)
    <th rowspan="{{ $rowspans[$index++] }}">{{ $matiere->lib_mat }}</th>
    @else @php ++$index; @endphp
    @endif
    @if($rowspans[$index] > 0)
    <th rowspan="{{ $rowspans[$index++] }}">{{ $matiere->lib_trimestre }}</th>
    @else @php ++$index; @endphp
    @endif
    @if($rowspans[$index] > 0)
    <th rowspan="{{ $rowspans[$index++] }}">{{ $matiere->lib_annee }}</th>
    @else @php ++$index; @endphp
    @endif
    </tr>
    @endforeach
    </table>

    Je suis parti du principe que je disposais d'une variable $rowspans avec la bonne valeur du rowspan pour chaque valeur. C'est syntaxiquement un peu lourd mais bon...

    Ensuite restait le gros morceau de création de ce tableau...

    Là aussi c'est un peu lourd mais ça fonctionne. Dans mon contrôleur :

    $matieres = Matiere::select('nom','note','dat_note','lib_mat','lib_trimestre','lib_annee')->get();

    // Première passe
    $matieresArray = $matieres->toArray();
    $columns = [];
    $i = -1;
    foreach($matieresArray as $item) {
    ++$i;
    $j = 0;
    foreach($item as $key => $value) {
    $columns[$j++][$i] = $value;
    }
    }

    // Deuxième passe
    $countAttributes = count($matieres->first()->getAttributes());
    $countRows = $matieres->count();
    $total = $countAttributes * $countRows;
    $rowspan = array_fill(0, $total, 1);
    $i = -$countRows;
    foreach($columns as $column) {
    $i += $countRows;
    for($j = $countRows - 1; $j > 0; --$j) {
    $value = $column[$j];
    if($value == $column[$j - 1]) {
    $rowspan[$i + $j -1] += $rowspan[$i + $j];
    $rowspan[$i + $j] = 0;
    }
    }
    }

    // Troisième passe
    $rowspans = [];
    for($i = 0; $i < $countRows; ++$i) {
    for($j = $i; $j < $total; $j += $countRows) {
    array_push($rowspans,$rowspan[$j]);
    }
    }

    return view('tableau', compact('matieres', 'rowspans'));

    Et voilà le résultat.

    Mon code est assez lourd et doit pouvoir être simplifié mais au moins ça te donne un exemple qui fait le boulot :)

    Une autre approche sans doute plus légère serait de faire le traitement en Javascript à l'arrivée mais c'est moins élégant.

  • Avatar de lavarelkyi
    Membre depuis :
    20/12/2017
    Messages :
    71

    Salut effectivement cela effectue le boulot,

    j'ai juste besoin de quelques explications par exemple au niveau de la vue sur ce code suivant :

    @if($rowspans[$index] > 0)

    <th rowspan="{{ $rowspans[$index++] }}">{{ $matiere->nom }}</th>

    @else @php ++$index; @endphp

    @endif

    et bien sûre sur chaque passe dans mon controller ...

    Merci encore pour votre reponse ...

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2178

    Salut,

    Au niveau de la vue c'est juste pour incrémenter l'indes à chaque valeur, mais on peut simplifier le code ainsi :

    <table>
    <tr>
    <th>Nom</th>
    <th>Notes</th>
    <th>Date notes</th>
    <th>Matières</th>
    <th>Trimestres</th>
    <th>Années</th>
    </tr>
    @php
    $index = -1;
    @endphp
    @foreach ($matieres as $matiere)
    <tr>
    @if($rowspans[++$index])
    <th rowspan="{{ $rowspans[$index] }}">{{ $matiere->nom }}</th>
    @endif
    @if($rowspans[++$index])
    <th rowspan="{{ $rowspans[$index] }}">{{ $matiere->note }}</th>
    @endif
    @if($rowspans[++$index])
    <th rowspan="{{ $rowspans[$index] }}">{{ $matiere->dat_note }}</th>
    @endif
    @if($rowspans[++$index])
    <th rowspan="{{ $rowspans[$index] }}">{{ $matiere->lib_mat }}</th>
    @endif
    @if($rowspans[++$index])
    <th rowspan="{{ $rowspans[$index] }}">{{ $matiere->lib_trimestre }}</th>
    @endif
    @if($rowspans[++$index])
    <th rowspan="{{ $rowspans[$index] }}">{{ $matiere->lib_annee }}</th>
    @endif
    </tr>
    @endforeach
    </table>

    La valeur dans $rowspans est soit 0 (on affiche pas la cellule), soit 1 (affichage normal), soit >1 on est dans le cas où on fusionne les cellules.

    Pour ce qui est des 3 passes. Au départ on a un tableau :

    array:4 [▼
    0 => array:6 [▼
    "nom" => "Emmanuel"
    "note" => "15/20"
    "dat_note" => "2018-10-26 00:00:00"
    "lib_mat" => "Maths"
    "lib_trimestre" => "trimestre 1"
    "lib_annee" => "2018"
    ]
    1 => array:6 [▼
    "nom" => "Emmanuel"
    "note" => "15/20"
    "dat_note" => "2018-10-25 00:00:00"
    "lib_mat" => "Maths"
    "lib_trimestre" => "trimestre 1"
    "lib_annee" => "2018"
    ]
    2 => array:6 [▶]
    3 => array:6 [▶]
    ]

    La première passe regroupe les valeurs en colonnes :

    array:6 [▼
    0 => array:4 [▼
    0 => "Emmanuel"
    1 => "Emmanuel"
    2 => "Emmanuel"
    3 => "Emmanuel"
    ]
    1 => array:4 [▼
    0 => "15/20"
    1 => "15/20"
    2 => "12/20"
    3 => "12/20"
    ]
    2 => array:4 [▼
    0 => "2018-10-26 00:00:00"
    1 => "2018-10-25 00:00:00"
    2 => "2018-10-24 00:00:00"
    3 => "2018-10-23 00:00:00"
    ]
    3 => array:4 [▶]
    4 => array:4 [▶]
    5 => array:4 [▶]
    ]

    La deuxième passe calcule le rowspan pour chaque valeur dans les colonnes :

    array:24 [▼
    0 => 4
    1 => 0
    2 => 0
    3 => 0
    4 => 2
    5 => 0
    6 => 2
    7 => 0
    8 => 1
    9 => 1
    10 => 1
    11 => 1
    12 => 3
    13 => 0
    14 => 0
    15 => 1
    16 => 4
    17 => 0
    18 => 0
    19 => 0
    20 => 4
    21 => 0
    22 => 0
    23 => 0
    ]

    La troisième passe remet en ordre pour correspondre au processus d'affichage des valeurs dans la vue parce qu'on affiche ligne par ligne et pas par colonne :

    array:24 [▼
    0 => 4
    1 => 2
    2 => 1
    3 => 3
    4 => 4
    5 => 4
    6 => 0
    7 => 0
    8 => 1
    9 => 0
    10 => 0
    11 => 0
    12 => 0
    13 => 2
    14 => 1
    15 => 0
    16 => 0
    17 => 0
    18 => 0
    19 => 0
    20 => 1
    21 => 1
    22 => 0
    23 => 0
    ]
  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2178

    Comme j'étais pas très satisfait de mon code j'ai simplifié le traitement en deux phases :

    $matieres = Matiere::select('nom','note','dat_note','lib_mat','lib_trimestre','lib_annee')->get();

    // Phase 1
    $matieresArray = $matieres->toArray();
    $temp = [];
    foreach($matieresArray as $item) {
    foreach($item as $key => $value) {
    array_push($temp, $value);
    }
    }

    // Phase 2
    $countAttributes = count($matieres->first()->getAttributes());
    $countRows = $matieres->count();
    $total = $countAttributes * $countRows;
    $rowspans = array_fill(0, $total, 1);
    for($i = $total - 1; $i >= $total - $countAttributes; --$i) {
    for($j = $i; $j >= $countAttributes; $j -= $countAttributes) {
    $value = $temp[$j];
    if($value == $temp[$j - $countAttributes]) {
    $rowspans[$j - $countAttributes] += $rowspans[$j];
    $rowspans[$j] = 0;
    }
    }
    }

    return view('tableau', compact('matieres', 'rowspans'));
  • Avatar de lavarelkyi
    Membre depuis :
    20/12/2017
    Messages :
    71

    Salut,

    Merci encore @bestmomo, cela m'aide énormement

  • Avatar de lavarelkyi
    Membre depuis :
    20/12/2017
    Messages :
    71

    Excusez moi beaucoup si je vous fatigue avec cette histoire d'affichage de ce tableau, mais j'ai une autre préoccupation qui concerne ce même tableau.

    Je souhaiterais l'afficher avec ajax, puisque l'affichage même de ce tableau dépend du matricule, du trimestre et bien sûre de l'année en cour.
    Et quand je dis depends cela voudrais dire tout simplement que l'utilisateur doit d'abord entrer le matricule, faire un choix du trimestre, selectionner l'année en cour et cliquer sur Rechercher pour afficher le tableau.

    Je souhaite le faire ainsi parce que cela évitera ainsi de recharger toute la page pour un simple affichage de tableau.

    Donc une suggestion de votre part sera la bien venue...

    Merci encore pour les précédentes interventions...

Vous ne pouvez pas répondre à ce sujet.