Traitement des données de modèle arbitraires

Dans ce tutoriel, nous allons parler de l’ajout de contenu hors base de données à nos modèles.

Dépôt de code à télécharger

Ce que nous allons couvrir

  • Vers quoi travaillons-nous?
  • Mise à jour du modèle: travail en arrière
  • Mise à jour du contrôleur pour utiliser des données génériques

 

Vers quoi travaillons-nous?

Jusqu’à présent, les données de nos modèles étaient plutôt unilatérales. Elle provient de la base de données et nous rendons les champs d’un ou plusieurs enregistrements renvoyés sur le modèle. Cependant, le modèle et la base de données ne sont pas si étroitement liés. Aucune règle ne dit que toutes les données de modèle doivent provenir de la base de données.

En fin de compte, ce que nous enseignons dans cette leçon est le concept des éléments de l’interface utilisateur composables . Comme vous le savez peut-être, les composants composables représentent une tendance de plus en plus rapide dans le développement d’applications, les développeurs et les concepteurs cherchant à maintenir un niveau élevé d’agilité et de réutilisabilité.

Étant composables, ces composants sont essentiellement “stupides” et ne savent vraiment que faire une chose: rendre une interface utilisateur basée sur la configuration qui leur a été transmise, ce que nous appellerons une composition .

Dans le cadre de notre projet, nous allons éclairer les boutons de bascule des filtres de recherche dans la barre latérale de notre page de recherche de propriétés. Le but de ces boutons est d’indiquer à l’utilisateur quels filtres de recherche ont été appliqués et de proposer une option pour les supprimer et actualiser la page de recherche.

 

Mise à jour du modèle: travail en arrière

De nombreux développeurs, y compris moi-même, trouvent qu’il est plus facile de revenir en arrière avec des problèmes comme celui-ci, ce qui signifie qu’il faut commencer par le modèle et ensuite ajouter le backend. Examinons ces boutons de filtre et essayons de les extraire pour en faire quelque chose que nous pouvons utiliser.

Comme nous pouvons le constater, elles sont toutes contenues de manière statique dans une ulbalise pour le moment.

 

<ul class="chzn-choices">
   <li class="search-choice"><span>New York</span><a href="#" class="search-choice-close"></a></li>
   <li class="search-choice"><span>Residential</span><a href="#" class="search-choice-close"></a></li>
   <li class="search-choice"><span>3 bedrooms</span><a href="#" class="search-choice-close"></a></li>
   <li class="search-choice"><span>2 bathrooms</span><a href="#" class="search-choice-close"></a></li>
   <li class="search-choice"><span>Min. $150</span><a href="#" class="search-choice-close"></a></li>
   <li class="search-choice"><span>Min. $400</span><a href="#" class="search-choice-close"></a></li>
</ul>

La mauvaise façon de le faire

Une approche qui pourrait vous venir à l’esprit consiste à utiliser une longue série de logique d’affichage pour générer toutes les options possibles, comme ceci:

 

<ul class="chzn-choices">
<% if $LocationFilter %>
   <li class="search-choice"><span>$LocationFilter</span><a href="#" class="search-choice-close"></a></li>
<% end_if %>

<% if $BedroomFilter %>
   <li class="search-choice"><span>$BedroomFilter bedrooms</span><a href="#" class="search-choice-close"></a></li>
<% end_if %>

<!-- etc... -->
</ul>

 

Cela peut sembler raisonnable au début, cela ne posera que des problèmes. Il y a un certain nombre de problèmes avec cette approche.

  • Cela pollue votre modèle avec la syntaxe et beaucoup de balisage répété
  • Il pollue votre contrôleur avec de nombreuses assignations de propriétés répétitives et / ou méthodes
  • Cela crée plus de parité entre votre contrôleur et votre modèle. Si vous souhaitez ajouter ou supprimer une nouvelle option de recherche, vous devez vous rappeler de mettre à jour le modèle.
  • Nous devons réutiliser la valeur du filtre comme étiquette , par exemple $BedroomFilter bedrooms, et à un moment donné, cela ne fonctionnera tout simplement pas. Les filtres de recherche ne sont souvent pas lisibles par l’homme, tels que les identifiants.

Une meilleure approche

Si la vue des libalises imbriquées dans un uldevient presque synonyme de <% loop %>contrôle pour vous, c’est bon signe. Nous allons certainement avoir besoin d’une boucle ici. Cela gardera le modèle d’interface utilisateur beaucoup plus propre et nous donnera plus de contrôle sur la sortie, car nous aurons l’occasion de composer chaque membre de la boucle. Ajoutons cela maintenant et faisons le reste au fur et à mesure.

<ul class="chzn-choices">
   <% loop $ActiveFilters %>
        <li class="search-choice"><span>New York</span><a href="#" class="search-choice-close"></a></li>
   <% end_loop %>
</ul>

 

Avez-vous du sens jusqu’ici? Encore une fois, nous travaillons à reculons, la $ActiveFilterspièce est donc simplement sémantique à l’heure actuelle.

Passons maintenant au brainstorming de noms de propriétés pour tout le contenu dynamique.

 

<% if $ActiveFilters %>
<div class="chzn-container-multi">
  <ul class="chzn-choices">
     <% loop $ActiveFilters %>
        <li class="search-choice"><span>$Label</span><a href="$RemoveLink" class="search-choice-close"></a></li>
     <% end_loop %>
  </ul>
</div>
<% end_if %>

 

Nous avons ajouté les propriétés $Labelet $RemoveLink, que nous pouvons supposer, sont les deux seuls traits distinctifs de chaque bouton de filtre.

 

Mise à jour du contrôleur

Maintenant que notre syntaxe de modèle est en place, nous devons configurer le contrôleur pour alimenter ces données avec le modèle. Nous pourrions écrire une nouvelle méthode appelée ActiveFilters()(ou getActiveFilters()) qui inspecte la demande et renvoie quelque chose, mais étant donné qu’il n’y a qu’un seul point de terminaison pour notre page de recherche, il est plus logique à ce stade du projet de créer les éléments de l’interface utilisateur de filtre à mesure qu’ils sont appliqués à la liste.

 

Créer une liste arbitraire

Afin d’invoquer le <% loop %>bloc, nous aurons bien sûr besoin d’une sorte de liste itérable. Jusqu’ici, nous utilisions SilverStripe\ORM\DataListune liste d’enregistrements associés à une requête de base de données. Puisque nos éléments d’interface utilisateur de filtre ne proviennent pas de la base de données, nous aurons besoin de quelque chose de plus primitif. Dans ce cas, SilverStripe\ORM\ArrayListc’est un choix idéal.

Au sommet de notre index()action, instancions cette liste.

app / src / PropertySearchPageController.php

 

//...
use SilverStripe\ORM\ArrayList;

class PropertySearchPageController extends PageController
{
    public function index(HTTPRequest $request)
    {
        $properties = Property::get();
        $activeFilters = ArrayList::create();

        //...
    }
    //...

 

Maintenant, il nous suffit de remplir notre liste avec des données.

Rappelez-vous ViewableData?

Pour remplir la liste, nous allons revenir sur notre vieil ami SilverStripe\View\ViewableDatadu tutoriel précédent. Tout comme un récapitulatif, ViewableDataest un objet primitif prêt à être rendu sur un modèle. Un type de ViewableDataest DataObject, que nous utilisons depuis le début pour rendre le contenu de la base de données.

Vous aurez rarement besoin d’utiliser la ViewableDataclasse elle-même, mais son descendant immédiat SilverStripe\View\ArrayDataest très flexible et ne pourrait être plus simple à mettre en œuvre. C’est fondamentalement juste un tableau à clé glorifié. Tout ce que vous avez à faire est de l’instancier avec un tableau de paires clé / valeur qui sera traduit en $Variablevariables de modèle et restituera les valeurs associées.

Ajoutons les détails du Keywordsfiltre.

app / src / PropertySearchPageController.php

 

//...
use SilverStripe\View\ArrayData;
use SilverStripe\Control\HTTP;

class PropertySearchPageController extends PageController
{

    public function index(HTTPRequest $request)
    {

        //...

        if ($search = $request->getVar('Keywords')) {
            $activeFilters->push(ArrayData::create([
                'Label' => "Keywords: '$search'",
                'RemoveLink' => HTTP::setGetVar('Keywords', null, null, '&'),
            ]));

            $properties = $properties->filter([
                'Title:PartialMatch' => $search
            ]);
        }

        //..

 

En utilisant la push()méthode ArrayList, nous y ajoutons des ArrayDataobjets. Chacun a Labelet RemoveLinkpropriétés, comme requis par le modèle. La RemoveLinkpropriété implémente une méthode utilitaire obscure de la SilverStripe\Control\HTTPclasse d’assistance. Tout ce qu’il fait est de prendre l’URI actuel et de définir un paramètre de requête donné sur une valeur donnée. Dans ce cas, nous le configurons nullpour supprimer efficacement le filtre.

Le filtre suivant concerne la plage de dates de disponibilité. Il n’offre en réalité pas beaucoup d’utilité pour l’utilisateur d’afficher ceci en tant que filtre basculable, d’autant plus qu’il s’agit d’un filtre composite de ArrivalDateet Nights, passons donc à celui-ci.

Les quelques suivantes, qui font toutes partie de notre boucle soignée, sont assez simples. Nous ajouterons un autre membre à la $filterKeysliste, qui sera un sprintf()modèle compatible pour générer l’étiquette pour chaque filtre.

app / src / PropertySearchPageController.php

 

    public function index(HTTPRequest $request)
    {

        //...

    $filters = [
        ['Bedrooms', 'Bedrooms', 'GreaterThanOrEqual', '%s bedrooms'],
        ['Bathrooms', 'Bathrooms', 'GreaterThanOrEqual', '%s bathrooms'],
        ['MinPrice', 'PricePerNight', 'GreaterThanOrEqual', 'Min. $%s'],
        ['MaxPrice', 'PricePerNight', 'LessThanOrEqual', 'Max. $%s'],
    ];

    foreach($filters as $filterKeys) {
        list($getVar, $field, $filter, $labelTemplate) = $filterKeys;
        if ($value = $request->getVar($getVar)) {
            $activeFilters->push(ArrayData::create([
                'Label' => sprintf($labelTemplate, $value),
                'RemoveLink' => HTTP::setGetVar($getVar, null, null, '&'),
            ]));

            $properties = $properties->filter([
                "{$field}:{$filter}" => $value
            ]);
        }
    }

        //...
    }

Passer les filtres au template

Tout comme notre variable personnalisée Results, nous allons passer la ActiveFiltersliste au modèle via un tableau.

app / src / PropertySearchPageController.php

 

    public function index(HTTPRequest $request)
    {

        //...

        $paginatedProperties = PaginatedList::create(
            $properties,
            $request
        )->setPageLength(15)
         ->setPaginationGetVar('s');

        $data = array (
            'Results' => $paginatedProperties,
            'ActiveFilters' => $activeFilters           
        );

        //...
    }

 

Rechargez la page, et vous devriez avoir des boutons de filtres de travail maintenant!

TOUT VOIR Ajouter une remarque
VOUS
Ajoutez votre commentaire
 
© Academy EdTech. 2019 All rights reserved.
X