Jiné renderování položek RadioListu

medhi
Generous Backer | 255
+
0
-

Výchozí Renderer vykresluje itemy radiolistu takto:

<label>
	<input type="radio" name="species" value="snowman" >
	Snowman
</label>

Já bych ale potřeboval vlastní renderer nastavit tak, aby se vypisovaly takto (nechci/nemůžu použít manuální renderování):

<input id="itemid1" type="radio" name="species" value="snowman" >
<label for="itemid1">Snowman</label>

Tedy ne vnořeně, ale za sebou. Předpokládám, že to nejde, už jenom kvůli tomu ID, které tam normálně není. Nikde jsem to řešení ani nenašel.

Můj důvod: Chci nastylovat label jako tlačítko a potřebuji mu nastavit jiný styl, pokud je input checked. To jde pouze v druhém případě (pomocí selectoru .input-class:checked+.label-class). V prvním případě to nejde, protože CSS nezná způsob, jak nastavit třídu rodiče konkrétního elementu (možná to půjde v budoucnu pseudoelementem :has()).

Díky moc

Ondřej Kubíček
Člen | 494
+
0
-

a není jednodušší, prostě jen když je radio checked, nastavit labelu nějakou třídu a nastylovat jak potřebuješ?

medhi
Generous Backer | 255
+
0
-

Ondřej Kubíček napsal(a):

a není jednodušší, prostě jen když je radio checked, nastavit labelu nějakou třídu a nastylovat jak potřebuješ?

To bohužel právě u toho vnořeného případu nejde. Neexistuje CSS selektor, který ti najde rodiče checknutého inputu.

Jan Tvrdík
Nette guru | 2595
+
+1
-

Pokud ten label obalíš <span> (do labelu můžeš předat Html instance), tak můžeš použít .input-class:checked + span

dakur
Člen | 493
+
0
-

@medhi Podle mě nemáš bez manual renderingu nebo JS šanci. Z hlediska frontenďáka uvažuješ správně, korektní struktura je opravdu taková a jinak to nezprovozníš – z povahy, jak + funguje.

<input>
<label>...</label>

Řeší se to tady ale opakovaně, že lidé potřebují drobnou úpravu rendereru, ale wrappers je málo a manual rendering zas moc. Myslím, že by stálo za to umožnit programátorovi nějak zasáhnout do struktury vykreslování formuláře, jen nevím jak. 🙂

medhi
Generous Backer | 255
+
0
-

dakur napsal(a):

@medhi Podle mě nemáš bez manual renderingu nebo JS šanci. Z hlediska frontenďáka uvažuješ správně, korektní struktura je opravdu taková a jinak to nezprovozníš – z povahy, jak + funguje.

<input>
<label>...</label>

Řeší se to tady ale opakovaně, že lidé potřebují drobnou úpravu rendereru, ale wrappers je málo a manual rendering zas moc. Myslím, že by stálo za to umožnit programátorovi nějak zasáhnout do struktury vykreslování formuláře, jen nevím jak. 🙂

Myslel jsem si to, díky. Budu bádat jak to udělat jinak a kouknu do zdrojáků, jestli by taková fíčura byla složitá na přidání.

medhi
Generous Backer | 255
+
0
-

Jan Tvrdík napsal(a):

Pokud ten label obalíš <span> (do labelu můžeš předat Html instance), tak můžeš použít .input-class:checked + span

To nejde, CSS selektor .input-class:checked + span najde:

<input class="input-class" checked> <span></span>

nikoli

<span>
	<label>
		<input type="radio" name="species" value="snowman" >
		Snowman
	</label>
</span>
dakur
Člen | 493
+
0
-

a kouknu do zdrojáků, jestli by taková fíčura byla složitá na přidání.

Já myslím, že nebyla. Myslím, že by stačilo jen mít někde nějaký Nette\Utils\Html parametr, který by reprezentoval DOM celého toho form fieldu. Pak by tam ještě musely být nějaké dva placeholdery, které by označkovaly, co je teda ten input a co label, aby s tím mohlo nette/forms dále pracovat a věšet na to své věci. Něco v tomto smyslu:

$radioList->setDOM(
  Html::el('div')
    ->addHtml(Html::el('input', [RadioList::INPUT_PLACEHOLDER]))
    ->addHtml(Html::el('label', [RadioList::LABEL_PLACEHOLDER])
         ->addHtml(Html::el('span')->setText('span inside of <label>')))
    ->addHtml(Html::el('span')->setText('another span after <label>'))
);

/* output:
 * <div> <-- this one implicitly by Nette or whatever group element is there by default
 *   <div>
 *     <input ...>
 *     <label ...>
 *       <span>span inside of &lt;label&gt;</span>
 *     </label>
 *     <span>another span after &lt;label&gt;</span>
 *   </div>
 * </div>
 */

Ale určitě by to chtělo někoho vzdělanějšího a s větším nadhledem než jsem já. 🙂

Editoval dakur (10. 3. 2021 14:46)

Kamil Valenta
Člen | 762
+
0
-

Pokud ten radiolist definuješ takto:

$form->addRadioList('test', 'TEST', [
	1 => \Nette\Utils\Html::el('span')->setText('1'),
	2 => \Nette\Utils\Html::el('span')->setText('2'),
]);

Získáš strukturu:

<label>
	<input type="radio" name="test" value="1" >
	<span>1</span>
</label>

A to už selektorem „+“ nastyluješ…

--
IMHO i @JanTvrdík tím „ten label“ nemyslel HTML značku, ale samotný popisek radio buttonu…

Editoval Kamil Valenta (15. 2. 2021 11:27)

medhi
Generous Backer | 255
+
0
-

Kamil Valenta napsal(a):

Pokud ten radiolist definuješ takto:

$form->addRadioList('test', 'TEST', [
	1 => \Nette\Utils\Html::el('span')->setText('1'),
	2 => \Nette\Utils\Html::el('span')->setText('2'),
]);

Získáš strukturu:

<label>
	<input type="radio" name="test" value="1" >
	<span>1</span>
</label>

A to už selektorem „+“ nastyluješ…

--
IMHO i @JanTvrdík tím „ten label“ nemyslel HTML značku, ale samotný popisek radio buttonu…

Pokud tedy pomocí CSS skryju <label> a <input> a nastyluju <span> jako tlačítko (viz. Můj důvod: Chci nastylovat label jako tlačítko a potřebuji mu nastavit jiný styl, pokud je input checked.), jak potom bude fungovat klikání na ten span, aby se měnila hodnota inputu?

Kamil Valenta
Člen | 762
+
-1
-

A není rychlejší to vyzkoušet? :)

<label> bych asi neskrýval, když je nadřazený tomu <span>.

<style type="text/css">
input {
    display: none;
}
input + span {
    padding: 10px;
    background: red;
}
input:checked + span {
    background: green;
}
</style>

<label>
	<input type="radio" name="test" value="1" >
	<span>1</span>
</label>

<label>
	<input type="radio" name="test" value="2" >
	<span>2</span>
</label>

Editoval Kamil Valenta (15. 2. 2021 13:21)

dakur
Člen | 493
+
0
-

😮 To není moc intuitivní API.. 🤔

@medhi Btw, stylovat label nebo cokoliv jiného jako tlačítko není vůbec dobrý nápad. Pokud potřebuješ tlačítko, použij tlačítko (tedy button) a změn styl. Jinak si koleduješ o user experience problém – viz https://www.vzhurudolu.cz/prirucka/button#…

Editoval dakur (15. 2. 2021 12:36)

medhi
Generous Backer | 255
+
0
-

Kamil Valenta napsal(a):

A není rychlejší to vyzkoušet? :)

<label> bych asi nezkrýval, když je nadřazený tomu <span>.

<style type="text/css">
input {
    display: none;
}
input + span {
    padding: 10px;
    background: red;
}
input:checked + span {
    background: green;
}
</style>

<label>
	<input type="radio" name="test" value="1" >
	<span>1</span>
</label>

<label>
	<input type="radio" name="test" value="2" >
	<span>2</span>
</label>

Máš naprostou pravdu, ten span je v label, takže klikání funguje. Docela pěknej hack, díky moc.

Má to tedy jednu nevýhodu – tlačítko <span> je uzavřeno v <label> a tedy nelze potom třeba použít Bootstrapí groupování tlačítek.

Editoval medhi (15. 2. 2021 12:49)

medhi
Generous Backer | 255
+
0
-

dakur napsal(a):

😮 To není moc intuitivní API.. 🤔

@medhi Btw, stylovat label nebo cokoliv jiného jako tlačítko není vůbec dobrý nápad. Pokud potřebuješ tlačítko, použij tlačítko (tedy button) a změn styl. Jinak si koleduješ o user experience problém – viz https://www.vzhurudolu.cz/prirucka/button#…

Není, ale je to jediná možnost, jak to udělat a vlastně to neni tak hrozný, jak jsem čekal, že by mohlo být.

Já nepotřebuji ani tak tlačítko, jako jakýsi „switch“, tedy radiobutton renderovat jako přepínač, v mém případě složený z komponent Bootstrapových tlačítek. Myslím, že to v tomto případě docela legitimní věc.

dakur
Člen | 493
+
0
-

Aha, takže ne tlačítko, ale přepínač, už chápu. 🙂 Bootstrap v5 ho má v sobě mimochodem, ale chápu, že kvůli tomu nejde upgradovat celý projekt. https://getbootstrap.com/…ecks-radios/#…

Editoval dakur (15. 2. 2021 12:58)

medhi
Generous Backer | 255
+
0
-

dakur napsal(a):

Aha, takže ne tlačítko, ale přepínač, už chápu. 🙂 Bootstrap v5 ho má v sobě mimochodem, ale chápu, že kvůli tomu nejde upgradovat celý projekt. https://getbootstrap.com/…ecks-radios/#…

Já to mám v5, ale tohle je checkbox switch, já potřebuju switch pro 3+ možnosti :) Tedy musím použít RadioList nebo Select.