Zend Framework

propose AutoCompleteDojoExt id=table id for example and label=name

Details

  • Type: Improvement Improvement
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: Zend_Controller
  • Labels:
    None

Description

if you have data from a DB table groepen

groepen [id,name]

name is what you want to show the user, id is what you need

I have a table offices
offices [id, name, groepen_id]

groepen_id is a FK tot groepen

with my function you can place a filterselect for offices that shows all the groepen by name.
when I save to the offices table I just use the id instead of the group name.

<select dojoType="dijit.form.FilteringSelect"
name="state3"
autocomplete="false"
value="CA">
<option value="1" selected="selected">California</option>
<option value="2" >Illinois</option>
<option value="3" >New York</option>
<option value="4" >Texas</option>
</select>

id is the value in this case, name is the text the user sees.
When the user clicks submit we can get the value (id) of the record the user selected.

solutions:

Groepen is a Zend_Db_Table and has id and name column

$groepen = new Groepen();
$this->_helper->autoCompleteDojoExt($groepen->fetchAll()->toArray());

<?php
/**

  • Zend Framework
    *
  • LICENSE
    *
  • This source file is subject to the new BSD license that is bundled
  • with this package in the file LICENSE.txt.
  • It is also available through the world-wide-web at this URL:
  • http://framework.zend.com/license/new-bsd
  • If you did not receive a copy of the license and are unable to
  • obtain it through the world-wide-web, please send an email
  • to license@zend.com so we can send you a copy immediately.
    *
  • @category Zend
  • @package Zend_Controller
  • @subpackage Zend_Controller_Action_Helper
  • @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  • @license http://framework.zend.com/license/new-bsd New BSD License
  • @version $Id: AutoCompleteDojo.php 9098 2008-03-30 19:29:10Z thomas $
    */

/**

  • @see Zend_Controller_Action_Helper_AutoComplete_Abstract
    */
    require_once 'Zend/Controller/Action/Helper/AutoComplete/Abstract.php';

/**

  • Create and send Dojo-compatible autocompletion lists
    *
  • @uses Zend_Controller_Action_Helper_AutoComplete_Abstract
  • @category Zend
  • @package Zend_Controller
  • @subpackage Zend_Controller_Action_Helper
  • @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  • @license http://framework.zend.com/license/new-bsd New BSD License
    */
    class Zend_Controller_Action_Helper_AutoCompleteDojoExt extends Zend_Controller_Action_Helper_AutoComplete_Abstract
    {
    /**
  • Validate data for autocompletion
  • @param mixed $data
  • @return boolean
    */
    public function validateData($data)
    {
    if (is_array($data) && isset($data['items']) && is_array($data['items'])) { return true; }

return false;
}

/**

  • Prepare data for autocompletion
  • @param mixed $data
  • @param boolean $keepLayouts
  • @return string
    */
    public function prepareAutoCompletion($data, $keepLayouts = false)
    Unknown macro: { $items = array(); foreach ($data as $value) { $items[] = array('label' => array_pop($value), 'name' => array_pop($value)); } $final = array( 'identifier' => 'name', 'items' => $items, ); return $this->encodeJson($final, $keepLayouts); }

    }

Activity

Hide
Matthew Weier O'Phinney added a comment -

How is this different than the current Dojo AutoComplete action helper? Can you summarize? I'd rather modify that to be more general than to add additional helpers that muddy the waters with more variants.

For the record, we plan to update the Dojo autocomplete action helper to utilize Zend_Dojo_Data, which will also give more flexibility. I'm also thinking that a flag and/or setters for specifying either FilteringSelect or ComboBox would help make it more useful.

Show
Matthew Weier O'Phinney added a comment - How is this different than the current Dojo AutoComplete action helper? Can you summarize? I'd rather modify that to be more general than to add additional helpers that muddy the waters with more variants. For the record, we plan to update the Dojo autocomplete action helper to utilize Zend_Dojo_Data, which will also give more flexibility. I'm also thinking that a flag and/or setters for specifying either FilteringSelect or ComboBox would help make it more useful.
Hide
Kristof Vansant added a comment -

controller:

Schoolgemeenschappen table [id, name]

public function schoolgemeenschapAction() { $schoolgemeenschappen = new Schoolgemeenschappen(); $this->_helper->autoCompleteDojoExt($schoolgemeenschappen->fetchAll()->toArray()); }

in form:

$this->addElement(
'FilteringSelect',
'scholengemeenschap_id',
array(
'label'=> 'Scholengemeenschap',
'storeId'=> 'stateStore1',
'storeType'=>'dojo.data.ItemFileReadStore',
'storeParams'=> array('url' => '/studiegids/school/schoolgemeenschap'),
'dijitParams' => array('searchAttr' => 'label',
'required' => 'true', ),)
);

in add and change record

$row->scholengemeenschap_id = $form->getValue('scholengemeenschap_id');

do you understand now?

with my new function you get:

{"identifier":"name","items":[{"label":"CLB-Kempen","name":"1"},{"label":"CLB-1 AMI","name":"2"}]}

with the current you get

{"identifier":"name","items":[{"label":"CLB-Kempen","name":"CLB-Kempen"},{"label":"CLB-1 AMI","name":"CLB-1 AMI"}]}

because of this code:

foreach ($data as $key => $value) { $items[] = array('label' => $value, 'name' => $value); }
$final = array(
'identifier' => 'name',
'items' => $items,
);

Show
Kristof Vansant added a comment - controller: Schoolgemeenschappen table [id, name] public function schoolgemeenschapAction() { $schoolgemeenschappen = new Schoolgemeenschappen(); $this->_helper->autoCompleteDojoExt($schoolgemeenschappen->fetchAll()->toArray()); } in form: $this->addElement( 'FilteringSelect', 'scholengemeenschap_id', array( 'label'=> 'Scholengemeenschap', 'storeId'=> 'stateStore1', 'storeType'=>'dojo.data.ItemFileReadStore', 'storeParams'=> array('url' => '/studiegids/school/schoolgemeenschap'), 'dijitParams' => array('searchAttr' => 'label', 'required' => 'true', ),) ); in add and change record $row->scholengemeenschap_id = $form->getValue('scholengemeenschap_id'); do you understand now? with my new function you get: {"identifier":"name","items":[{"label":"CLB-Kempen","name":"1"},{"label":"CLB-1 AMI","name":"2"}]} with the current you get {"identifier":"name","items":[{"label":"CLB-Kempen","name":"CLB-Kempen"},{"label":"CLB-1 AMI","name":"CLB-1 AMI"}]} because of this code: foreach ($data as $key => $value) { $items[] = array('label' => $value, 'name' => $value); } $final = array( 'identifier' => 'name', 'items' => $items, );
Hide
Kristof Vansant added a comment -

this function keeps the old one working
if one array is given id and name are the same (the old functionality)
when you use a multidimensional array it will use my code.

<?php
/**

  • Zend Framework
    *
  • LICENSE
    *
  • This source file is subject to the new BSD license that is bundled
  • with this package in the file LICENSE.txt.
  • It is also available through the world-wide-web at this URL:
  • http://framework.zend.com/license/new-bsd
  • If you did not receive a copy of the license and are unable to
  • obtain it through the world-wide-web, please send an email
  • to license@zend.com so we can send you a copy immediately.
    *
  • @category Zend
  • @package Zend_Controller
  • @subpackage Zend_Controller_Action_Helper
  • @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  • @license http://framework.zend.com/license/new-bsd New BSD License
  • @version $Id: AutoCompleteDojo.php 9098 2008-03-30 19:29:10Z thomas $
    */

/**

  • @see Zend_Controller_Action_Helper_AutoComplete_Abstract
    */
    require_once 'Zend/Controller/Action/Helper/AutoComplete/Abstract.php';

/**

  • Create and send Dojo-compatible autocompletion lists
    *
  • @uses Zend_Controller_Action_Helper_AutoComplete_Abstract
  • @category Zend
  • @package Zend_Controller
  • @subpackage Zend_Controller_Action_Helper
  • @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  • @license http://framework.zend.com/license/new-bsd New BSD License
    */
    class Zend_Controller_Action_Helper_AutoCompleteDojo extends Zend_Controller_Action_Helper_AutoComplete_Abstract
    {
    /**
  • Validate data for autocompletion
  • @param mixed $data
  • @return boolean
    */
    public function validateData($data)
    {
    if (is_array($data) && isset($data['items']) && is_array($data['items'])) { return true; }

return false;
}

/**

  • Prepare data for autocompletion
  • @param mixed $data
  • @param boolean $keepLayouts
  • @return string
    */
    public function prepareAutoCompletion($data, $keepLayouts = false)
    {

$items = array();
if(count($data)===count($data, COUNT_RECURSIVE)){

foreach ($data as $key => $value) { $items[] = array('label' => $value, 'name' => $value); }

}else{

foreach ($data as $value) { $items[] = array('label' => array_pop($value), 'name' => array_pop($value)); }

}

$final = array(
'identifier' => 'name',
'items' => $items,
);

return $this->encodeJson($final, $keepLayouts);
}

}
?>

Show
Kristof Vansant added a comment - this function keeps the old one working if one array is given id and name are the same (the old functionality) when you use a multidimensional array it will use my code. <?php /**
  • Zend Framework *
  • LICENSE *
  • This source file is subject to the new BSD license that is bundled
  • with this package in the file LICENSE.txt.
  • It is also available through the world-wide-web at this URL:
  • http://framework.zend.com/license/new-bsd
  • If you did not receive a copy of the license and are unable to
  • obtain it through the world-wide-web, please send an email
  • to license@zend.com so we can send you a copy immediately. *
  • @category Zend
  • @package Zend_Controller
  • @subpackage Zend_Controller_Action_Helper
  • @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  • @license http://framework.zend.com/license/new-bsd New BSD License
  • @version $Id: AutoCompleteDojo.php 9098 2008-03-30 19:29:10Z thomas $ */
/**
  • @see Zend_Controller_Action_Helper_AutoComplete_Abstract */ require_once 'Zend/Controller/Action/Helper/AutoComplete/Abstract.php';
/**
  • Create and send Dojo-compatible autocompletion lists *
  • @uses Zend_Controller_Action_Helper_AutoComplete_Abstract
  • @category Zend
  • @package Zend_Controller
  • @subpackage Zend_Controller_Action_Helper
  • @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  • @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Controller_Action_Helper_AutoCompleteDojo extends Zend_Controller_Action_Helper_AutoComplete_Abstract { /**
  • Validate data for autocompletion
  • @param mixed $data
  • @return boolean */ public function validateData($data) { if (is_array($data) && isset($data['items']) && is_array($data['items'])) { return true; }
return false; } /**
  • Prepare data for autocompletion
  • @param mixed $data
  • @param boolean $keepLayouts
  • @return string */ public function prepareAutoCompletion($data, $keepLayouts = false) {
$items = array(); if(count($data)===count($data, COUNT_RECURSIVE)){ foreach ($data as $key => $value) { $items[] = array('label' => $value, 'name' => $value); } }else{ foreach ($data as $value) { $items[] = array('label' => array_pop($value), 'name' => array_pop($value)); } } $final = array( 'identifier' => 'name', 'items' => $items, ); return $this->encodeJson($final, $keepLayouts); } } ?>
Hide
Kristof Vansant added a comment -

old json output:

{"identifier":"name","items":[{"label":{"id":"1","vestigingnaam":"Geel"},"name":{"id":"1","vestigingnaam":"Geel"}},{"label":{"id":"2","vestigingnaam":"Mol"},"name":{"id":"2","vestigingnaam":"Mol"}},{"label":{"id":"3","vestigingnaam":"Westerlo"},"name":{"id":"3","vestigingnaam":"Westerlo"}},{"label":{"id":"4","vestigingnaam":"Vorselaar"},"name":{"id":"4","vestigingnaam":"Vorselaar"}},{"label":{"id":"5","vestigingnaam":"Turnhout"},"name":{"id":"5","vestigingnaam":"Turnhout"}},{"label":{"id":"6","vestigingnaam":"Zoersel"},"name":{"id":"6","vestigingnaam":"Zoersel"}},{"label":{"id":"7","vestigingnaam":"Hoogstraten"},"name":{"id":"7","vestigingnaam":"Hoogstraten"}},{"label":{"id":"8","vestigingnaam":"Herentals"},"name":{"id":"8","vestigingnaam":"Herentals"}}]}

mine json output:

{"identifier":"name","items":[{"label":"Geel","name":"1"},{"label":"Mol","name":"2"},{"label":"Westerlo","name":"3"},{"label":"Vorselaar","name":"4"},{"label":"Turnhout","name":"5"},{"label":"Zoersel","name":"6"},{"label":"Hoogstraten","name":"7"},{"label":"Herentals","name":"8"}]}

Show
Kristof Vansant added a comment - old json output: {"identifier":"name","items":[{"label":{"id":"1","vestigingnaam":"Geel"},"name":{"id":"1","vestigingnaam":"Geel"}},{"label":{"id":"2","vestigingnaam":"Mol"},"name":{"id":"2","vestigingnaam":"Mol"}},{"label":{"id":"3","vestigingnaam":"Westerlo"},"name":{"id":"3","vestigingnaam":"Westerlo"}},{"label":{"id":"4","vestigingnaam":"Vorselaar"},"name":{"id":"4","vestigingnaam":"Vorselaar"}},{"label":{"id":"5","vestigingnaam":"Turnhout"},"name":{"id":"5","vestigingnaam":"Turnhout"}},{"label":{"id":"6","vestigingnaam":"Zoersel"},"name":{"id":"6","vestigingnaam":"Zoersel"}},{"label":{"id":"7","vestigingnaam":"Hoogstraten"},"name":{"id":"7","vestigingnaam":"Hoogstraten"}},{"label":{"id":"8","vestigingnaam":"Herentals"},"name":{"id":"8","vestigingnaam":"Herentals"}}]} mine json output: {"identifier":"name","items":[{"label":"Geel","name":"1"},{"label":"Mol","name":"2"},{"label":"Westerlo","name":"3"},{"label":"Vorselaar","name":"4"},{"label":"Turnhout","name":"5"},{"label":"Zoersel","name":"6"},{"label":"Hoogstraten","name":"7"},{"label":"Herentals","name":"8"}]}
Hide
Kristof Vansant added a comment -

There is an issue with my multi column detection
when only one row is given the detection uses the old dojo generation code even if it should use mine.

So don't use the code which I proposed.

Matthew if you need a tester for your code, let me know I'm happy to beta test it.

Show
Kristof Vansant added a comment - There is an issue with my multi column detection when only one row is given the detection uses the old dojo generation code even if it should use mine. So don't use the code which I proposed. Matthew if you need a tester for your code, let me know I'm happy to beta test it.
Hide
Regis Leroy added a comment -

Personnally I just changed 2 few things to get this autocompleteDojo working:

public function prepareAutoCompletion($data, $keepLayouts = false)
{
$items = array();
foreach ($data as $key => $value) {
$items[] = array('label' => $value, 'name' => $value, 'key' => $key);
}
$final = array(
'identifier' => 'key',
'items' => $items,
);
return $this->encodeJson($final, $keepLayouts);
}

--> added key in the line and changed the 'identifier from 'name' to 'key'

Then with this HTML code I get my autocomplete working, showing names and using Id on my form destination:

<form id="Find_Form" action="/ce/fiche/edit" method="get" dojoType="dijit.form.Form">
<div dojoType="custom.FindAutoCompleteReadStore" jsId="NameStore" url="/ce/fiche/find/format/json" requestMethod="get"></div>
<label for="id" class="optional">Recherchez un nom:</label>
<span class="formelement">
<select name="id" id="FindByName" hasDownArrow="" store="NameStore" size="25" tabindex="99" autocomplete="1" dojoType="dijit.form.FilteringSelect" pageSize="10" >
</select></span>
<span class="actionbuttons"><input id="Find_go" name="Find_go" value="Go:" type="submit" label="go:"dojoType="dijit.form.Button" /></span>
</form>

Show
Regis Leroy added a comment - Personnally I just changed 2 few things to get this autocompleteDojo working:
public function prepareAutoCompletion($data, $keepLayouts = false) { $items = array(); foreach ($data as $key => $value) { $items[] = array('label' => $value, 'name' => $value, 'key' => $key); } $final = array( 'identifier' => 'key', 'items' => $items, ); return $this->encodeJson($final, $keepLayouts); }
--> added key in the line and changed the 'identifier from 'name' to 'key' Then with this HTML code I get my autocomplete working, showing names and using Id on my form destination:
<form id="Find_Form" action="/ce/fiche/edit" method="get" dojoType="dijit.form.Form"> <div dojoType="custom.FindAutoCompleteReadStore" jsId="NameStore" url="/ce/fiche/find/format/json" requestMethod="get"></div> <label for="id" class="optional">Recherchez un nom:</label> <span class="formelement"> <select name="id" id="FindByName" hasDownArrow="" store="NameStore" size="25" tabindex="99" autocomplete="1" dojoType="dijit.form.FilteringSelect" pageSize="10" > </select></span> <span class="actionbuttons"><input id="Find_go" name="Find_go" value="Go:" type="submit" label="go:"dojoType="dijit.form.Button" /></span> </form>
Hide
Regis Leroy added a comment -

one more point, for your sub-array detection why don't you use is_array($value) ?

Show
Regis Leroy added a comment - one more point, for your sub-array detection why don't you use is_array($value) ?
Hide
Kristof Vansant added a comment -

your probably right

how would you do following code?

'onChange'=> "stateStore2 = new dojo.data.ItemFileReadStore({url: '/studiegids/overzichtschool/studierichting/onderwijsvormid/'+ dijit.byId('onderwijsvorm_id').getValue() }); dijit.byId('studierichting_id').store = stateStore2; dijit.byId('studierichting_id').setDisplayedValue('');",
b
adding this will requery statestore2. Because it passes an id, the query will give other results. Because of this the dojo datastore gets other values.

Show
Kristof Vansant added a comment - your probably right how would you do following code? 'onChange'=> "stateStore2 = new dojo.data.ItemFileReadStore({url: '/studiegids/overzichtschool/studierichting/onderwijsvormid/'+ dijit.byId('onderwijsvorm_id').getValue() }); dijit.byId('studierichting_id').store = stateStore2; dijit.byId('studierichting_id').setDisplayedValue('');", b adding this will requery statestore2. Because it passes an id, the query will give other results. Because of this the dojo datastore gets other values.
Hide
Regis Leroy added a comment -

I'm not sure of what you're asking for. But I think that if you want to re-query your store you should use soething based on QueryReadStore instead. I wrote an example here:
http://www.makina-corpus.org/2008/10/26/autocomplete-ajax-search-with-dojo-and-zend-framework/

Show
Regis Leroy added a comment - I'm not sure of what you're asking for. But I think that if you want to re-query your store you should use soething based on QueryReadStore instead. I wrote an example here: http://www.makina-corpus.org/2008/10/26/autocomplete-ajax-search-with-dojo-and-zend-framework/
Hide
Christopher Weldon added a comment -

What's the status of this? This gets to be particularly problematic for things such as trying to do State Code => State name mapping with either a ComboBox or FilteringSelect and the only thing being outputted to the screen is just the State name...

Show
Christopher Weldon added a comment - What's the status of this? This gets to be particularly problematic for things such as trying to do State Code => State name mapping with either a ComboBox or FilteringSelect and the only thing being outputted to the screen is just the State name...
Hide
Matthew Weier O'Phinney added a comment -

The Dojo autocomplete action helper was converted to Zend_Dojo_Data in 1.7.0, released in November 2008. It can either create a Zend_Dojo_Data object, or consume one. If you need to specify different keys for the identifier and/or label, pass your data to a new instance of Zend_Dojo_Data, and then pass that to the helper:

// Use "id" as the identifier, "name" as the label:
$data = new Zend_Dojo_Data('id', $items, "name");
$this->_helper->autoCompleteDojo($data);

If I do not hear any feedback one way or the other on whether or not the above solution addresses this issue (at this point, I'm not even entirely certain what issue is actually being reported), I will close the bug.

Show
Matthew Weier O'Phinney added a comment - The Dojo autocomplete action helper was converted to Zend_Dojo_Data in 1.7.0, released in November 2008. It can either create a Zend_Dojo_Data object, or consume one. If you need to specify different keys for the identifier and/or label, pass your data to a new instance of Zend_Dojo_Data, and then pass that to the helper:
// Use "id" as the identifier, "name" as the label:
$data = new Zend_Dojo_Data('id', $items, "name");
$this->_helper->autoCompleteDojo($data);
If I do not hear any feedback one way or the other on whether or not the above solution addresses this issue (at this point, I'm not even entirely certain what issue is actually being reported), I will close the bug.

People

Vote (1)
Watch (2)

Dates

  • Created:
    Updated: