I've looked through the Views issue queue and haven't found much on this; but I cannot seem to get exposed filter inputs to be accepted in a programmatic context.
In the module I'm writing, I want the autocomplete widget on a form to either utilize a pre-defined view display and pass the autocomplete text to the view as an exposed filter input for Node:Title.
According to "Starting Views 2 Documentation" (http://groups.drupal.org/node/10129), it should be as simple as:
<?php
$view->exposed_input['filter_identifier'] = 'filter_value';
?>
But, that didn't work.
Next, I found code in another issue as follows:
<?php
$view->set_exposed_input(array('identifier' => 'title', 'value' => $searchstr));
?>
But, that didn't work either.
Attached is my current "view" object, and a snippet from the module I'm working on. Any help would be greatly appreciated.
From my module:
<?php
/**
* Looks up ACTIVE products in the system which PERMIT registration.
* Generates a JSON array for use in autocomplete widgets.
*/
function uc_product_registration_productreference_autocomplete($searchstr) {
$searchstr = check_plain( $searchstr );
// see if a view is defined that lists active products
// in this way, admins can define what products are 'active'
// based on any criteria they want
$view = views_get_view('product_registration');
if ( $view ) {
// not sure why, but Views doesn't allow me to
// pass the display NAME as the ID parameter
// we'll have to include a DEFAULT view for this.
$display_id = 'block_1';
$view->is_cacheable = FALSE;
$view->set_display($display_id);
$view->set_exposed_input(array('identifier' => 'title', 'value' => $searchstr));
$view->build($display_id);
$view->execute($display_id);
if (!$view->execute()) {
// there was a problem.
print drupal_json(array());
exit();
}
// if the view is defined and we can execute it
// collect data from here instead of the rest of this function.
$results = array();
// scan through each result from the view
// REMEMBER: $result is an OBJECT of type stdClass !!!
foreach ($view->result AS $obj) {
// limit the title length to a safe number of characters
$title = substr( check_plain($obj->node_title), 0, 42);
$index = sprintf("%s [nid: %d]", $title, $obj->nid);
// index the result
$results[$index] = $title;
}
// send data back to the browser and exit.
print drupal_json($results);
exit();
}
...
...
?>
| Comment | File | Size | Author |
|---|---|---|---|
| views-exposed-filters-in-code--myview.txt | 5.26 KB | wjaspers |
Comments
Comment #1
wjaspers commentedwhoops, noticed I'm calling Execute twice ... but even if I remove the latter, the problem still persists.
Comment #2
Letharion commentedComment #3
wjaspers commentedSolved it!
I'm not sure if this is a bug; but I changed:
<?php ... $view->set_exposed_input(array('identifier' => 'title', 'value' => $searchstr)); ... ?>TO:
<?php ... $view->exposed_data['title'] = $searchstr; ... ?>and now it works.
I was under the impression that "set_exposed_input" was supposed to assign values to exposed input filters in my view; but, I couldn't find ANY documentation on it.
Comment #4
merlinofchaos commentedIt should be:
Comment #5
merlinofchaos commentedAlso your code is missing a $view->pre_execute() just prior to the build -- that will be necessary to ensure hook_pre_view is run and pager settings are set from the display. I guess if the default pager settings are adequate you won't NEED this, but if you don't run it you'll always get exactly 10 items.
Comment #6
wjaspers commentedSo, does
array('identifier'=>'value', ...)setup the exposed filter? Or is it intended as a method to place values INTO the view? Ispre_execute()required when setting an exposed filter's value? The hook documentation forhook_view_pre_execute()doesn't really describe much... Is there anything special you recommend I do in this hook?The 10 items doesn't bother me so much since we're searching by node title; and in the module I'm applying this to, I'll include a default view that includes a "block" for this purpose. Since I'm using this as an "autocomplete" finder, the number of items is restricted to 10 anyway.
Is there any way to enforce that a filter is always present? Even if someone were to override the default views I include?
Comment #7
merlinofchaos commentedUsing set_exposed_input() is the same as having the values present in the query parameters of the URL. In fact, if there is no input already set, Views itself more or less does $view->exposed_input = $_GET; One note about using set_exposed_input: You must set *all* of the fields necessary for the exposed filters or they will just go to their default values.
You don't need to do anything with pre_execute(), it's just best form to call it prior to build() because it is part of the normal workflow and skipping it could have difficult to find side effects. Maybe not specifically in this case, but you never know what will happen down the road.
You could look in $view->filter and examine what filters exist. If the filter isn't present you could create it manually. This is...rather tricky as you have to have a pretty good understanding of the system to be able to create a filter manually. Not recommended for most developers.
Comment #8
wjaspers commentedOk; that sums it up for me. Exposed inputs are intended for query parameters and won't work unless all are accounted for (kinda like a bus on a fieldtrip: if anyone's missing, the bus can't leave).
I was just thinking of having a filter "locked in", so that the node title is always the flexible parameter for my autocomplete. I realize now this might not be practical, but its good to know. Thanks for your help!