SuggestInput (autocomplete) pro Nette 2.3.3
- Croc
- Člen | 270
Vypátral jsem o jaký Typeahaed se jedná (Twitter typeahead). Akorát stále nevím, jak dostat potřebná data do addTypeahead:
Container::extensionMethod('addTypeahead', function(Container $container, $name, $label = NULL, $callback = NULL) {
return $container[$name] = new Controls\Typeahead($label, $callback);
});
Editoval Croc (22. 6. 2015 19:45)
- Unlink
- Člen | 298
No callback ktorý bude získavať tie dáta napíšeš v php
$form->addTypeahead('name', 'Titulok', function($q) {
return $this->daco->getItemsBy($q); //v $q je to čo užívateľ zadal
});
O zvyšok by sa mal postarať javascript ktorý tam už je.
Čo sa týka toho dotazu do db, to je na tebe, ako ten daný callback implementuješ.
Editoval Unlink (22. 6. 2015 21:29)
- Croc
- Člen | 270
Takže třeba takto?
// Formulář:
$form->addTypeahead('item', 'Název:', function($q) {
return $this->utilsManager->getItemBy($q); });
// Příkaz do DB:
public function getItemBy($q)
{
return $this->database->table(self::TABLE_ITEM)->select(self::ITEM_NAME)->where("".self::ITEM_NAME." LIKE ?", '%$q%');
}
// V šabloně formuláře:
var countries = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.whitespace,
queryTokenizer: Bloodhound.tokenizers.whitespace,
// url points to a json file that contains an array of country names, see
// https://github.com/twitter/typeahead.js/blob/gh-pages/data/countries.json
prefetch: '../data/item.json'
});
// passing in `null` for the `options` arguments will result in the default
// options being used
$('.typeahead').typeahead(null, {
name: 'item',
source: item
});
Pořád moc nerozumím, jak se data dostanou do JS.
Editoval Croc (23. 6. 2015 12:05)
- Croc
- Člen | 270
Pokud využiji klasickou variantu s polem v JS, ze kterého se data načtou, s tím problém samozřejmě nemám. Pokud bych chtěl využít variantu Prefetch s .json, tak pokud tomu odhaduji dobře, musím načtená data z DB uložit do .json (napsat si sám – JS to nemumí???), ze kterého se budou načítat dle výše uvedeného JS.
Bohužel Nextras nemá žádnou dokumentaci pro implementaci typeahead, tak nemám žádnou představu jak to tedy je…
- Croc
- Člen | 270
Aktuálně to mám následovně:
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="{$basePath}/js/typeahead.js"></script> // ten co je použitý v Nextras Demo
//formulář:
$form->addTypeahead('states', 'Plemeno:', function($q) {
return $this->utilsManager->getItemBy($q); });
//implementace getItemBy()
public function getItemBy()
{
return $this->database->table(self::TABLE_ITEM)->select(self::BREED_ITEM)->where("".self::ITEM_NAME." LIKE ?", "'%".$q."%'")->fetch();
}
// JS init
jQuery(function($) {
$('.typeahead').each(function() {
$(this).typeahead({
remote: {
url: $(this).attr('data-typeahead-url'),
wildcard: '__QUERY_PLACEHOLDER__'
}
});
});
});
Stále nechápu (dle @hrach a @Unlink) jak z getItemBy() se můžou dostat data do JS při načtení stránky. Dle této impelentace to nefunguje a už si opravdu nevím rady :-( Prosím o pomoc
Editoval Croc (26. 6. 2015 20:10)
- Pavel Kravčík
- Člen | 1205
@Croc: Teď jsem řešil něco podobného jako ty. Problém je ve verzích typeahead. Většina příkladů nefunguje v 0.10.5, ale jen v 0.11. Pokud však nahraješ 0.11 – často to „zprasí“ ostatní doplňky (mě např. Grido).
Místo toho jsem použil https://jqueryui.com/autocomplete a funguje to skvěle.
$('#dealer').autocomplete({
lookup: [{ data: 1, value: 'Jednička' }],
onSelect: function (suggestion) {
alert(suggestion.data);
}
});
- Croc
- Člen | 270
Zdravím, zkouším rozchodit selectize dle @Oli, ale narazil jsem na problém. Asi dělám něco špatně. Chtěl bych použít variantu výběru jedné položky (Single Item Select).
Instalaci jsem provedl dle návodu
v config.neon mám:
extensions:
selectize: App\Form\Control\SelectizeExtension
selectize:
mode: select # second mode is `select` for selection just 1 option
valueField: id
labelField: name
searchField: name
Vytvořil jsem si zkušební pole a vytvořil formulář:
$arrayData = [
0 => [
"id" => 1,
"name" => "Item One"],
1 => [
"id" => 2,
"name" => "Item Two"],
2 => [
"id" => 3,
"name" => "Item Three"],
3 => [
"id" => 4,
"name" => "Item Four"]
];
$form = new Form;
$form->addSelectize('tags', 'Text:', $arrayData);
//......
Výsledkem je toto
HTML kód daného objektu:
<select class="selectize form-control" data-options="{"mode":"select","create":true,"maxItems":null,"delimiter":"…,"valueField":"id","labelField":"name","searchField":"name"}" data-entity="[{"id":1,"name":"Item One"},{"id":2,"name":"Item Two"},{"id":3,"name":"Item Three"},{"id":4,"name":"Item Four"}]" name="tags">
<optgroup label="0">
::before
<option value="id">
1
</option>
<option value="name">
Item One
</option>
</optgroup>
<optgroup label="1"></optgroup>
//......
</select>
Pokud použiju fullmode, zobrazí se pouze input bez nápovědy.
Nevíte kde by mohl být problém prosím?
Editoval Croc (10. 7. 2015 15:00)
- Croc
- Člen | 270
Taky me to napadlo, ale zatim jsem to nezkousel. Diky za tip. Ale stejne je tu problem, asi s js, nefunguje ten input. V mod full s vyse uvedeny polem nejde napoveda. S mod select semzobrazi pouze list bez moznosti psani…
EDIT:
Ted ještě koukám, že ve FF v konzoli je zobrazena chyba: TypeError: MicroPlugin is undefined
řádek MicroPlugin.mixin(Selectize);:
//......
self.initializePlugins(self.settings.plugins);
self.setupCallbacks();
self.setupTemplates();
self.setup();
};
// mixins
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MicroEvent.mixin(Selectize);
MicroPlugin.mixin(Selectize); //tento řádek
// methods
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$.extend(Selectize.prototype, {
//......
Nemůže to být tím?
Editoval Croc (10. 7. 2015 17:15)
- Croc
- Člen | 270
v @layout.latte mám:
{include content}
</div>
{block scripts}
<script src="//nette.github.io/resources/js/netteForms.min.js"></script>
<script src="{$basePath}/js/live-form-validation.js"></script>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="{$basePath}/js/bootstrap.js"></script>
<script src="{$basePath}/js/bootstrap-datepicker.js"></script>
<script src="{$basePath}/js/locales/bootstrap-datepicker.cs.min.js"></script>
<script src="{$basePath}/js/datepicker.init.js"></script>
<script src="{$basePath}/js/selectize.js"></script> // samotný selectize
<script src="{$basePath}/js/selectize.init.js"></script> // soubor z client-side
{/block}
</body>
</html>
Jak máš na mysli „nekde pod nim selectize()?“ ? To se musí ještě někde ručně volat?
- vojty
- Člen | 19
kzk_cz napsal(a):
@Croc: Teď jsem řešil něco podobného jako ty. Problém je ve verzích typeahead. Většina příkladů nefunguje v 0.10.5, ale jen v 0.11. Pokud však nahraješ 0.11 – často to „zprasí“ ostatní doplňky (mě např. Grido).
Místo toho jsem použil https://jqueryui.com/autocomplete a funguje to skvěle.
$('#dealer').autocomplete({ lookup: [{ data: 1, value: 'Jednička' }], onSelect: function (suggestion) { alert(suggestion.data); } });
Ahoj, jak si to vyřešil s tim gridem? Napsal sis vlastní implementaci 0.11 pro Grido?
- Croc
- Člen | 270
Pavel Kravčík napsal(a):
@Croc: Teď jsem řešil něco podobného jako ty. Problém je ve verzích typeahead. Většina příkladů nefunguje v 0.10.5, ale jen v 0.11. Pokud však nahraješ 0.11 – často to „zprasí“ ostatní doplňky (mě např. Grido).
Místo toho jsem použil https://jqueryui.com/autocomplete a funguje to skvěle.
$('#dealer').autocomplete({ lookup: [{ data: 1, value: 'Jednička' }], onSelect: function (suggestion) { alert(suggestion.data); } });
Tak jsem nerozchodil ani ten selectize… Jsem kopito asi… Poslední nadějí je tedy autocomplete. Povedlo se mi rozchodit ten příklad z odkazu co udáváš, ale budu mít problém dostat tam data z DB. Mohl by jsi mě prosím trochu nasměrovat? Je nějaká možnost přiřadit ID k danému záznamu? Abych pak zpětně nemusel vyhledávat zadaný text pro ID položky v DB.
Autocomplete jsem používal bez Nette, ale s Nette nevím jak tam dostat ty data spolu s ID…
Díky moc
EDIT:
Tak mi to nedalo a zkusil jsem ještě ten selectize. Vypadá to, že jsem ho
částečně rozchodil :-) Problém akorát je, že zde mám předvyplněnou
první hodnotu z pole při načtení formuláře.
Editoval Croc (7. 8. 2015 20:43)
- Oli
- Člen | 1215
@Croc Pokud jsi v modu select
, tak to je normální. To
by se mělo chovat uplně stejně jako addSelect
z nette. Jestli
tam jsou nějaký rozdíly, tak to je bug.
Pokud to máš v modu full
, tak to je divný, protože se mě
to nikdy nestalo a proto si i myslím, že to máš v tom select modu.
Řešení je jednoduché, prostě tomu nastav
setPromt('-- Vyberte --');
Btw. Pokud by jsi potřeboval ty data tahat dynamicky z databáze, tak to selectize taky umí. Je to ta sekce Remote Source — Github. Ten nette doplněk to by default neumí, nikdy jsem to zatím nepotřeboval. Pokud tě ale napadne nějaký univerzální řešení, jak to zanést do toho doplňku, tak to bude super!
- Croc
- Člen | 270
Ahoj,
potřeboval bych se zeptat na jednu věc. Jak použít addSelectize například
ve 2 formulářích. V jednom formuláři bude mode selecet a
v druhém full.
Jde mi o to, že volba módu se provádí v configu a nebo přímo na daném poli, ale to mi nefunguje:
$form->addSelectize('id_category', 'label.category', $this->utilsManager->loadCategory($this->translator->getLocale(), $this->item_category), ['mode' => 'select'])
->setRequired('validate.field_required')
->setPrompt('input.choose_category');
Pokud tedy odstraním mode: select z configu a nastavím ho dle kódu výše, stane se z toho klasický list.
Nevíte kde by mohl být problém?
Editoval Croc (4. 3. 2016 10:40)
- Oli
- Člen | 1215
Zkus https://github.com/…electize.php#L50. Ale nemelo by to na to mit vliv. Taky to tak pouzivam. Mozna zkus jeste
[
'mode' => 'select',
'class' => 'another-class'
]
Podivej se taky jestli nemas v js error.
- Croc
- Člen | 270
Díky za tip, setMode jsem taky předtím zkoušel, ale výsledek stejný. Něco je špatně, protože mi teď nejde ani to co mi předtím fungovalo (mode pouze v konfigu). JS ale žádnou chybu nehlásí… Mazal jsem cache a taky nepomohlo… Zkusím se v tom pohrabat
BTW Tohle se mi jednou už stalo (nakonec jsem musel nakopčit původní soubory ze zálohy). Sranda je, že byly beze změny, ale pak to začalo fungovat.
- Oli
- Člen | 1215
Jeste me napadlo, mám tam dost nešťastně ten js obalenej v selectize(). Tak jestli to voláš někde v tom js. Zkus si tam dát nějakej alert, jestli se tam dostaneš. Vím, že mě tohle taky jednou vypeklo, že jsem tu funkci zapomněl zavolat. Přilinkovat soubor totiž nestačí…
- Croc
- Člen | 270
Hm, teď už mi nefunguje selectize vůbec ani s původními soubory…
@layout.latte mám toto:
{**
* @param string $basePath web base path
* @param array $flashes flash messages
*}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{ifset title}{include title|striptags} | {/ifset}</title>
<link rel="shortcut icon" href="{$basePath}/favicon.ico">
<link rel="stylesheet" href="{$basePath}/css/bootstrap.css">
<link rel="stylesheet" href="{$basePath}/css/datepicker3.css">
<link rel="stylesheet" href="{$basePath}/css/selectize.bootstrap3.css">
<link rel="stylesheet" href="{$basePath}/css/basic.css">
<link rel="stylesheet" href="{$basePath}/css/dropzone.css">
<link rel="stylesheet" href="{$basePath}/css/style.css">
<link rel="stylesheet" href="{$basePath}/js/pictures/magnific-popup.css">
{block head}{/block}
</head>
<body>
{control menu}
<div class="container">
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
<div class="alert alert-danger" role="alert">
{$flash->message}
</div>
</div>
<br/><br/>
{include content}
</div>
<br/><br/>
<footer class="footer" role="navigation">
<div class="container">
<p class="navbar-text pull-left"><small>© 2011<small></p>
</div>
</footer>
{block scripts}
<script src="{$basePath}/js/live-form-validation.js"></script>
<!--<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>-->
<script src="{$basePath}/js/jquery-1.9.1.min.js"></script>
<script src="{$basePath}/js/nette.ajax.js"></script>
<script src="{$basePath}/js/bootstrap.js"></script>
<script src="{$basePath}/js/bootstrap-datepicker.js"></script>
<script src="{$basePath}/js/locales/bootstrap-datepicker.cs.min.js"></script>
<script src="{$basePath}/js/datepicker.init.js"></script>
<!--<script src="http://brianreavis.github.io/selectize.js/js/selectize.js"></script>-->
<script src="{$basePath}/js/selectize.js"></script>
<script src="{$basePath}/js/selectize.init.js"></script>
<script src="{$basePath}/js/moment.js"></script>
<script src="{$basePath}/js/MyValidation.js"></script>
<script src="{$basePath}/js/jquery.picture.min.js"></script>
<script src="{$basePath}/js/pictures/jquery.magnific-popup.js"></script>
<script src="{$basePath}/js/pictures/jquery.magnific-popup.min.js"></script>
<script>
$(function () {
$.nette.init();
});
$('.zoom-gallery').each(function() {
$(this).magnificPopup({
delegate: 'a',
type: 'image',
closeOnContentClick: false,
closeBtnInside: false,
mainClass: 'mfp-with-zoom mfp-img-mobile',
image: {
verticalFit: true,
titleSrc: function(item) {
return item.el.attr('title') + ' · <a class="image-source-link" href="'+item.el.attr('data-source')+'" target="_blank">image source</a>';
}
},
gallery: {
enabled: true
},
zoom: {
enabled: true,
duration: 300, // don't foget to change the duration also in CSS
opener: function(element) {
return element.find('img');
}
}
});
});
</script>
{/block}
</body>
</html>
Definice pole pro formulář:
$form->addSelectize('id_category', 'label.category', $this->utilsManager->loadCategory($this->translator->getLocale(), $this->item_category), ['mode' => 'select'])
->setAttribute('class', 'selectize-input')
->setRequired('validate.field_required')
->setPrompt('input.choose_category');
selectize.js je odtud: Git
selectize.init.js mám: Git
Selectize se mi tedy už chytá. ale je zobrazen špatně a nefunguje
(nezobrazí se list a nefunguje typeahead).
Problém bude v načtení nastavení pro selectize: https://lh3.googleusercontent.com/…T%25255D.png
Editoval Croc (4. 3. 2016 13:11)
- Oli
- Člen | 1215
Nevidím tam nikde to selectize()
v javascriptu. Další věcí
je, že nastavuješ třídu selectize-input
. To znamená, že by
jsi to měl odchytit v js. Já to mám třeba takhle:
$.nette.ext({
load: function() {
selectize();
selectize(undefined, '.author-selectize', function (options) {
options.onOptionAdd = function(value) {
$('.authorEmail').parent().parent().show();
};
return options;
});
}
});
Uznávám, že pořadí parametrů není optimální, ale vznikalo to genericky… :-)