PRESENTED TO
Cra Crazy zy Tri Trick cks s wi with th Vi View ews
Amani Mansour and Krystee Dryer
Cra Crazy zy Tri Trick cks s wi with th Vi View ews - - PowerPoint PPT Presentation
Cra Crazy zy Tri Trick cks s wi with th Vi View ews PRESENTED TO Amani Mansour and Krystee Dryer Vi View ews s Mo More re tha than Ju Just st Li List sts When do views cross over to complex? How to approach a complex
PRESENTED TO
Amani Mansour and Krystee Dryer
❶ When do views cross over to complex? ❷ How to approach a complex view. ❸ How to use hooks and javascript to get
the results you need.
DrupalCon 2018: Crazy Tricks with Views
Amani Mansour
Software Engineer
Krystee Dryer
Technical Lead and Senior Software Engineer
DrupalCon 2018: Crazy Tricks with Views
We’re Hiring!
4
A full service digital experience agency
Nonprofit Marketing & Fundraising Changing the World UX & Visual Design Web & Mobile Development
+ + =
Voters has multiple leagues across the U.S.
easy for users to find their nearest local league by zip code
DrupalCon 2018: Crazy Tricks with Views
If no zip code is entered, show a summary list
DrupalCon 2018: Crazy Tricks with Views
If a zip code is entered, display the league with that matching zip code and show the state league
DrupalCon 2018: Crazy Tricks with Views
Outcome #3: No Matching Zip Code Found
If a matching zip code is not found, display all leagues in the same state as the zip code and show the state league
DrupalCon 2018: Crazy Tricks with Views
Created a view page display
○
Fields:
∙ League type ∙ Title
○
Filter Criteria:
∙ Published ∙ Content Type = Local League ∙ League Type = Local League ∙ Zip Code (exposed)
DrupalCon 2018: Crazy Tricks with Views
Contextual Filter
∙ Content: Has taxonomy term ID
∙ Display summary when filter value is not in the URL ∙ Display record count with link
DrupalCon 2018: Crazy Tricks with Views
DrupalCon 2018: Crazy Tricks with Views
DrupalCon 2018: Crazy Tricks with Views
Created a view block display
○
Fields:
∙ League type ∙ Title
○
Filter Criteria:
∙ Published ∙ Content Type = Local League ∙ League Type = State League
DrupalCon 2018: Crazy Tricks with Views
Contextual Filter
∙ Content: State
∙ When filter value not available, provide default value = Has taxonomy term id from url ∙ Load default filter from term page, load default filter from node page, limit terms by vocab = state, filter to items that share all terms
DrupalCon 2018: Crazy Tricks with Views
Added the state league view block to the footer of the local league page view using a global view area
DrupalCon 2018: Crazy Tricks with Views
The state league is missing because the state tid is not in the url when a user searches by zip code
DrupalCon 2018: Crazy Tricks with Views
league
○
Display all leagues in the same state as the zip code entered if it did not match any results
○
Display state league
View Limitations
DrupalCon 2018: Crazy Tricks with Views
HOOK_views_pre_view – can be used to change things before the view is executed.
function lwv_views_pre_view(ViewExecutable $view, $display_id, array &$args) { if ($view->id() == 'local_leagues_by_state') { $exposedinput = $view->getExposedInput(); $zip = $exposedinput['field_zip_code_value']; if ($zip) { $args[0] = _get_state_by_zip($zip);
} } } If a zip code is entered, get the state where that zip code is located Get the input from the filter
DrupalCon 2018: Crazy Tricks with Views
DrupalCon 2018: Crazy Tricks with Views
HOOK_views_post_execute – can be used to alter results after the view is executed but before it is displayed.
function module_views_post_execute(ViewExecutable $view) { if ($view->id() == 'local_leagues_by_state') { if (!$view->total_rows) { $exposedinput = $view->getExposedInput(); $zip = $exposedinput['field_zip_code_value']; if ($zip) { $args = _get_state_by_zip($zip); // kint($args); die; if($args) { $response = new RedirectResponse('/local-leagues/find-local-league/' . $args . '?field_zip_code_value='); $response->send();
} } } } }
Test to see if view returns any results Send zip code to function and return state Once a state is returned, put it in the URL for the view to use as a contextual filter Grab the value of the zip code entered by the user
DrupalCon 2018: Crazy Tricks with Views
we created that allows us to pass it a zip code value and it will return the state where that zip code exists
Google Maps Geocoding API
DrupalCon 2018: Crazy Tricks with Views
function _get_state_by_zip($zip) { $uri = 'https://maps.googleapis.com/maps/api/geocode/json?address='. $zip .'&sensor=true&key=[key]'; try { $response = \Drupal::httpClient()->get($uri, array('headers' => array('Accept' => 'text/plain'))); $data = (string) $response->getBody(); if (empty($data)) { return FALSE; } } catch (RequestException $e) { return FALSE; } $dataArray = json_decode($data); $state = NULL; foreach($dataArray->results[0]->address_components as $data) { if ($data->types[0] == 'administrative_area_level_1') { $state = $data->long_name; } } if($state) { $term = \Drupal::entityTypeManager()
$ids = array_keys($term); return reset($ids); } return FALSE; } Call the google map geocoding api with zip
code and get response Response is in JSON format so we decode that into an object State information is held in the adminstrative_area_level_1 Use the state name obtained from the response and locate the taxonomy term that matches and get tid
Outcome #3: Achieved
DrupalCon 2018: Crazy Tricks with Views
Create a view switcher that allows users to switch the display between a card and list view
DrupalCon 2018: Crazy Tricks with Views
display
DrupalCon 2018: Crazy Tricks with Views
Header
○ Global text
area with html markup for the view switcher
DrupalCon 2018: Crazy Tricks with Views
instances
pattern .masonry( ‘methodName’ /* arguments */ )
DrupalCon 2018: Crazy Tricks with Views
Masonry functionality and will return the element back to its pre-initialized state
DrupalCon 2018: Crazy Tricks with Views
When masonry initializes it adds positioning on the masonry items (inline CSS). When it’s destroyed it removes what is added.
DrupalCon 2018: Crazy Tricks with Views
When the value of the select list changes If the select list value is equal to list view, then add the class ‘destroy- masonry’, else remove the class ‘destroy-masonry’
DrupalCon 2018: Crazy Tricks with Views
(function ($) { BF.init(function () { $('select[name="view-switcher"]').on( 'change', function() { var selectListValue = $(this).val(); var $masonryLayoutWrapper = $('.masonry-layout'); if(selectListValue == 'list-view'){ $masonryLayoutWrapper.addClass('destroy-masonry'); } else { $masonryLayoutWrapper.removeClass('destroy-masonry'); } }); }); })(jQuery);
DrupalCon 2018: Crazy Tricks with Views
filters with requirements Better Exposed Filters couldn’t solve
with checkboxes and selected filters in horizontal container
DrupalCon 2018: Crazy Tricks with Views
Multiselect as a base for the dropdowns
for the selected filters
DrupalCon 2018: Crazy Tricks with Views
custom module needed
multiselect.js file in the js directory
DrupalCon 2018: Crazy Tricks with Views
multiselect_facets
multiselect_facets: css: theme: css/multiselect_facets.css: {} js: js/multiselect_facets.js: {} dependencies:
bootstrap_multiselect: js: js/bootstrap-multiselect.js: {} dependencies:
DrupalCon 2018: Crazy Tricks with Views
Define custom javascript library Define the bootstrap- multiselect javascript library
/** * Implements hook_form_views_exposed_form_alter(). * */ function multiselect_facets_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) { $form['#attached']['library'][] = 'multiselect_facets/multiselect_facets'; $form['#attached']['library'][] = 'multiselect_facets/bootstrap_multiselect'; } /** * Implements hook_theme(). */ function multiselect_facets_theme() { return [ 'multiselect_facets' => [ 'variables' => [] ], ]; }
DrupalCon 2018: Crazy Tricks with Views
Using a hook_form_FORM_ID_alter() to find everywhere the exposed filters is used and attach libraries Some changes must be made to the exposed filter markup
DrupalCon 2018: Crazy Tricks with Views
Allow the bootstrap multiselect to attach to form items that have an attribute of multiple=multiple
(function ($) { 'use strict'; Drupal.behaviors.facets = { 'attach': function (context, settings) { var $context = $(context); $('select[multiple="multiple"]').multiselect();
DrupalCon 2018: Crazy Tricks with Views
google map
a dropdown by the name of the content (node) and return all nodes with same name
satisfy this requirement (dropdown and keyword search working together)
DrupalCon 2018: Crazy Tricks with Views
allows custom fields, filters, sorts and other components for views to be created
functionality and leverage what Drupal already done for us
DrupalCon 2018: Crazy Tricks with Views
dropdown box with the capabilities of a keyword search
your plugin after an existing one in core
plugin to start
DrupalCon 2018: Crazy Tricks with Views
custom module needed
InOperator.php from the views module in core
DrupalCon 2018: Crazy Tricks with Views
modulename
DrupalCon 2018: Crazy Tricks with Views
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) { parent::init($view, $display, $options); $this->valueTitle = t('Allowed program titles'); $this->definition['options callback'] = array($this, 'generateOptions'); }
Basic init function that initializes the new views filter plugin
DrupalCon 2018: Crazy Tricks with Views
public function generateOptions() { $query = \Drupal::database()->select('node_field_data', 'node_field_data'); $query->fields('node_field_data', array('nid', 'title')); $query->condition('node_field_data.status', '1'); $query->condition('node_field_data.type', 'program', 'IN'); $query->orderBy('node_field_data.title', 'ASC'); $data = $query->execute(); $results = $data->fetchAll(\PDO::FETCH_OBJ); $options = array(); foreach ($results as $result) { // $options[$result->nid] = substr($result->title, strpos($result->title, '- ') ); $program = explode(" | ", $result->title); $options[$program[1]] = $program[1]; $options = array_unique($options); natsort($options); } return $options;
}
Query the database to get the
Loop through the results and discard duplicates and set to alphabetical order by title Return the options for the filter
DrupalCon 2018: Crazy Tricks with Views
protected function opSimple() { if (empty($this->value)) { return; } $this->ensureMyTable(); $this->realField = 'title'; $programtitles = NULL; $where = db_or(); foreach ($this->value as $programtitle) { $where->condition( "$this->tableAlias.$this- >realField", '%' . db_like(trim($programtitle, " ,!?")) . '%', 'LIKE'); } $this->query->addWhere($this->options['group'], $where);
}
protected function opSimple() { if (empty($this->value)) { return; } $this->ensureMyTable(); // We use array_values() because the checkboxes keep keys and that can cause // array addition problems. $this->query->addWhere($this->options['group'], "$this->tableAlias.$this->realField", array_values($this->value), $this->operator); }
Customized function Original Function Add the where condition to the query to turn this into a keyword search
Amani Mansour
Amani.mansour@beaconfire-red.com
Krystee Dryer
Krystee.dryer@beaconfire-red.com
DrupalCon 2018: Crazy Tricks with Views