Drupal 8 - how to get exposed filters value in preprocess_views_view - drupal-views

I'm using preprocess_views_view to define some new variables and pass them to a twig template.
In order to define these variables I need to access the exposed filters input values, but I can't seem to figure out how:
function my_modules_preprocess_views_view(&$variables) {
$view = $variables['view'];
// Here I would need to access the exposed filters value
$exposed_filter_value = "the_value";
$variables["foo"] = "Something based on the exposed filters value";
}
I would be very grateful for any clues - cheers!

In a hook_preprocess_views_view() implementation in your theme or module:
$values = $view->getExposedInput();
// for example $values["color"];
Or, you can access the values directly from the views-view.html.twig template:
// Assuming `color` is configured to be the Filter identifier in the
// view's Filter Criteria exposed filter.
{{ view.getExposedInput.color }}

I had problems with #Hubert's solution and managed to get it to work with:
$variables["searchInputValue"] = $view->exposed_raw_input['query'];

Related

Retrieve content element field from within a plugin template?

I am modifying the template of a plugin, and I want to retrieve a field from the content element.
Using f:debug I see the only data available is from the plugin itself, and none from the content element.
Is there any way I can perhaps insert the field I need in the plugin settings?
eg. something like:
plugin.tx_plugin.settings {
contentUid = TEXT
contentUid.field = uid
}
The best way I can think of to do this is with a custom ViewHelper. Something like:
namespace MyVendor\MyExtension\ViewHelpers;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
class ContentUidViewHelper extends AbstractViewHelper
{
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
{
$configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
return $configurationManager->getContentObject()->data['uid'];
}
}
In your Fluid template:
<mynamespace:contentUid />
This will get the uid of the content element, but you can get any field this way. Just change the key of the data array to the field you need.
In the corresponding method (like the listAction or showAction) of the controller you can get the data of the content element in the following way:
$contentObject = $this->configurationManager->getContentObject();
$this->view->assign('contentObjectData', $contentObject->data);
As far as I know, you can't get to that data using typoscript, but I've never needed it anyway since I've been using the above code in the controller.
settings do not have stdWrap-type per default, but only string. So you can not use cObjects as values.
For one (or a few) settings, you could do the stdWrap-processing in your method/class yourself:
$settingsAsTypoScriptArray = $this->objectManager->get(TypoScriptService::class)->convertPlainArrayToTypoScriptArray($this->settings);
$contentObj = $this->configurationManager->getContentObject();
if ($contentObj === null) {
$contentObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
}
// now override the values in the settings array with the processed value
$contentUid = (int)$contentObj->stdWrap($settingsAsTypoScriptArray['contentUid'], $settingsAsTypoScriptArray['contentUid.']);
If you wanna have many settings to be stdWraped, have a look into EXT:news. Georg implemented an interesting concept via useStdWrap configuration.

How can customData can be binded with JavaScript

In the affected application is a responsive table whose ColumnListItems are added via JavaScript code. Now the lines should be highlighted by the highlighting mechanism depending on their state. The first idea was to control the whole thing via a normal controller function. I quickly discarded the idea, since the formatter is intended for such cases. So I created the appropriate Formatter function and referenced it in the JavaScript code. The call seems to work without errors, because the "console.log" is triggered in each case. Also the transfer of fixed values is possible without problems. However, the values I would have to transfer are located within customData of each line...
No matter how I try to form the path I get an "undefined" or "null" output.
I have already tried the following paths:
"/edited"
"/customData/edited"
"mAggregations/customData/0/mProperties/value"
"/mAggregations/items/0/mAggregations/customData/0/mProperties/value"
The code from Controller.js (with consciously differently indicated paths):
var colListItem = new sap.m.ColumnListItem({
highlight: {
parts: [{
path: "/mAggregations/items/0/mAggregations/customData/0/mProperties/value"
}, {
path: "/edited"
}],
formatter: Formatter.setIndication
},
cells: [oItems]
});
// first parameter to pass while runtime to the formatter
colListItem.data("editable", false);
// second paramter for the formatter function
colListItem.data("edited", false);
oTable.addItem(colListItem);
The code from Formatter.js:
setIndication: function (bEditable, bEdited) {
var sReturn;
if (bEditable && bEdited) {
// list item is in edit mode and edited
sReturn = "Error";
} else if (bEditable || bEdited) {
// list item is in edit mode or edited
sReturn = "Success";
} else {
sReturn = "None";
}
return sReturn;
}
The goal would also be for the formatter to automatically use the value of the model in order to avoid its own implementation of a listener, etc.
I hope one of you has a good/new idea that might bring me a solution :)
Many thanks in advance!
You cannot bind against the customData. Because the customData is located in the element, it is like a property.
Thats why you defined it here on colListItem: colListItem.data("key", value)
You only can bind against a model.
So I see three solutions
Store the information in a separate local JSON model whereof you can speficy your binding path to supply the values to your formatter
Do not supply the information via a binding path to the formatter, but read a model/object/array from a global variable in the controller holding the information via this (=controller) in formatter function
Store the information in the customData of each element and access the element reference in the formatter function via this(=ColumnListItem).data().
Passing the context to the formatter similar to this formatter: [Formatter.setIndication, colListItem]
Cons of 1. and 2: you need a key for a respective lookup in the other model or object.
From what I understand I would solve it with solution 3.

zend framework this->url get different url on the same page but different url

in application\modules\admin\layouts\scripts\layout.phtml
<?php echo $this->url(array('action'=>'logout','controller'=>'user','module'=>'admin'),null,true);?>
when I visited zfmul/public/admin-cate/ , It return
/zfmul/public/admin-cate/logout
but when I visited zfmul/public/admin/categories, It return
/zfmul/public/admin/user/logout
and the two url is render to the same module, same controller, same action, I wonder why it retrun different result?
I didi some configs in application.ini,
resources.router.routes.admincategories.route = "admin-cate/:action/:id"
resources.router.routes.admincategories.defaults.module = "admin"
resources.router.routes.admincategories.defaults.controller = "categories"
resources.router.routes.admincategories.defaults.action = "index"
resources.router.routes.admincategories.reqs.action = "save|edit|index|new"
resources.router.routes.admincategories.defaults.id = "1"
resources.router.routes.admincategories.reqs.id = "\d+"
When you use $this->url, you're in fact using function url from library/Zend/View/Helper/Url.php, whose 1st line is:
$router = Zend_Controller_Front::getInstance()->getRouter();
Since you declared a custom admincategories route, you now have 2 to access those particular module/controller/actions:
Default - accessible via zfmul/public/admin/categories;
Custom - accessible via zfmul/public/admin-cate/.
Depending on the URL you use to access, the $router variable value will change accordingly and so will the result of the $this->url call as you're experiencing.
Here are a few references to questions on SO that might help you work around that behaviour:
Zend Framework: How to disable default routing?;
Zend framework: Removing default routes.

Is there a generic way of setting field values in mapper from list of values?

Is there a way of creating method for setting the value in the Model's fields without setting the values explicitly like -
ModelName.create.fieldName1("value").fieldName2("value2") and so on
Can we iterate through all available fields of that model and set their values form some list-of-values ?
something like ...
Model.allFields.foreach((fld)=> {
fld.set(valueList(indx)); indx+=1
}
Actually I want to set values into all models using some generic method that works for all models.
According to my comment:
val list = List(...)
val record = YourRecordClass.createRecord
record.allFields.zip(list).foreach {case(field,value) => field.setFromAny(value)}

CodeIgniter: URIs and Forms

I'm implementing a search box using CodeIgniter, but I'm not sure about how I should pass the search parameters through. I have three parameters: the search string; product category; and the sort order. They're all optional. Currently, I'm sending the parameters through $_POST to a temporary method, which forwards the parameters to the regular URI form. This works fine. I'm using a weird URI format though:
http://site.com/products/search=computer,sort=price,cat=laptop
Does anyone have a better/cleaner format of passing stuff through?
I was thinking of passing it into the products method as arguments, but since the parameters are optional things would get messy. Should I suck it up, and just turn $_GET methods on? Thanks in advance!
Query Strings
You can enable query strings in CodeIgniter to allow a more standard search function.
Config.php
$config['enable_query_strings'] = FALSE;
Once enabled, you can accept the following in your app:
http://site.com/products/search?term=computer&sort=price&cat=laptop
The benefit here is that the user will find it easy to edit the URL to make a quick change to their search, and your search uses common search functionality.
The down side of this approach is that you are going against one of the design decisions of the CodeIgniter development team. However, my personal opinion is that this is OK provided that query strings are not used for the bulk of your content, only for special cases such as search queries.
A much better approach, and the method the CI developers intended, is to add all your search parameters to the URI instead of a query string like so:
http://site.com/products/search/term/computer/sort/price/cat/laptop
You would then parse all the URI segments from the 3rd segment ("term") forward into an array of key => value pairs with the uri_to_assoc($segment) function from the URI Class.
Class Products extends Controller {
...
// From your code I assume you are calling a search method.
function search()
{
// Get search parameters from URI.
// URI Class is initialized by the system automatically.
$data->search_params = $this->uri->uri_to_assoc(3);
...
}
...
}
This would give you easy access to all the search parameters and they could be in any order in the URI, just like a traditional query string.
$data->search_params would now contain an array of your URI segments:
Array
(
[term] => computer
[sort] => price
[cat] => laptop
)
Read more about the URI Class here: http://codeigniter.com/user_guide/libraries/uri.html
If you're using a fixed number of parameters, you can assign a default value to them and send it instead of not sending the parameter at all. For instance
http://site.com/products/search/all/somevalue/all
Next, in the controller you can ignore the parameter if (parameter == 'all'.)
Class Products extends Controller {
...
// From your code I assume that this your structure.
function index ($search = 'all', $sort = 'price', $cat = 'all')
{
if ('all' == $search)
{
// don't use this parameter
}
// or
if ('all' != $cat)
{
// use this parameter
}
...
}
...
}