Skip to content

Commit cb024b1

Browse files
committed
UK translation (Nette stands with Ukraine 💙💛)
1 parent d14777a commit cb024b1

File tree

161 files changed

+29229
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

161 files changed

+29229
-0
lines changed

application/uk/@home.texy

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Nette Application
2+
*****************
3+
4+
.[perex]
5+
Пакет `nette/application` є основою для створення інтерактивних веб-додатків.
6+
7+
- [Як працюють додатки? |how-it-works]
8+
- [Bootstrap |Bootstrap]
9+
- [Презентери |presenters]
10+
- [Шаблони |templates]
11+
- [Модулі |modules]
12+
- [Маршрутизація |routing]
13+
- [Створення URL-посилань |creating-links]
14+
- [Інтерактивні компоненти |components]
15+
- [AJAX і сніпети |ajax]
16+
- [Multiplier |Multiplier]
17+
- [Конфігурація |configuration]
18+
19+
20+
Встановлення
21+
------------
22+
23+
Завантажте та встановіть пакет за допомогою [Composer |best-practices:composer]:
24+
25+
```shell
26+
composer require nette/application
27+
```
28+
29+
| версія пакета | сумісна версія PHP
30+
|-----------------------|-----------------------
31+
| Nette Application 4.0 | PHP 8.0 - 8.1
32+
| Nette Application 3.1 | PHP 7.2 - 8.1
33+
| Nette Application 3.0 | PHP 7.1 - 8.0
34+
| Nette Application 2.4 | PHP 5.6 - 8.0
35+
36+
Застосовується до останніх версій патчів.

application/uk/@left-menu.texy

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Додаток Nette
2+
*************
3+
- [Як працюють додатки? |how-it-works]
4+
- [Bootstrap |Bootstrap]
5+
- [Презентери |presenters]
6+
- [Шаблони |templates]
7+
- [Модулі |modules]
8+
- [Маршрутизація |routing]
9+
- [Створення URL-посилань |creating-links]
10+
- [Інтерактивні компоненти |components]
11+
- [AJAX і сніпети |ajax]
12+
- [Multiplier |Multiplier]
13+
- [Конфігурація |configuration]
14+
15+
16+
Подальше читання
17+
****************
18+
- [Кращі практики |best-practices:]
19+
- [Усунення неполадок |nette:troubleshooting]

application/uk/ajax.texy

+266
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
AJAX і сніпети
2+
**************
3+
4+
<div class=perex>
5+
6+
Сучасні веб-додатки сьогодні працюють наполовину на сервері, а наполовину в браузері. AJAX є життєво важливим об'єднуючим фактором. Яку підтримку пропонує фреймворк Nette?
7+
- надсилання фрагментів шаблонів (так званих *сніпетів*)
8+
- передача змінних між PHP і JavaScript
9+
- Налагодження додатків AJAX
10+
11+
</div>
12+
13+
AJAX-запит може бути виявлений за допомогою методу сервісу [інкапсуляція HTTP-запиту |http:request] `$httpRequest->isAjax()` (визначає на основі HTTP-заголовка `X-Requested-With`). Існує також скорочений метод у презентері: `$this->isAjax()`.
14+
15+
AJAX-запит нічим не відрізняється від звичайного - викликається презентер з певним поданням і параметрами. Від презентера також залежить, як він відреагує: він може використати свої процедури для повернення фрагмента HTML-коду (сніпету), XML-документа, об'єкта JSON або фрагмента коду Javascript.
16+
17+
Існує попередньо оброблений об'єкт `payload`, призначений для надсилання даних у браузер у форматі JSON.
18+
19+
```php
20+
public function actionDelete(int $id): void
21+
{
22+
if ($this->isAjax()) {
23+
$this->payload->message = 'Успішно';
24+
}
25+
// ...
26+
}
27+
```
28+
29+
Для повного контролю над виведенням JSON використовуйте метод `sendJson` у презентері. Це негайно перерве роботу презентера, і ви обійдетеся без шаблону:
30+
31+
```php
32+
$this->sendJson(['key' => 'value', /* ... */]);
33+
```
34+
35+
Якщо ми хочемо надіслати HTML, ми можемо встановити спеціальний шаблон для AJAX-запитів:
36+
37+
```php
38+
public function handleClick($param): void
39+
{
40+
if ($this->isAjax()) {
41+
$this->template->setFile('path/to/ajax.latte');
42+
}
43+
// ...
44+
}
45+
```
46+
47+
48+
Naja .[#toc-naja]
49+
=================
50+
51+
[Бібліотека Naja |https://naja.js.org] використовується для обробки AJAX-запитів на стороні браузера. [Встановіть |https://naja.js.org/#/guide/01-install-setup-naja] його як пакет node.js (для використання з Webpack, Rollup, Vite, Parcel та іншими):
52+
53+
```shell
54+
npm install naja
55+
```
56+
57+
...або вставити безпосередньо в шаблон сторінки:
58+
59+
```html
60+
<script src="https://unpkg.com/naja@2/dist/Naja.min.js"></script>
61+
```
62+
63+
64+
Сніпети .[#toc-snippety]
65+
========================
66+
67+
Однак існує набагато потужніший інструмент вбудованої підтримки AJAX - сніпети. Їхнє використання дає змогу перетворити звичайний застосунок на AJAX-додаток за допомогою лише кількох рядків коду. Як усе це працює, показано в прикладі Fifteen, код якого також доступний у збірці або на [GitHub |https://github.com/nette-examples/fifteen].
68+
69+
Принцип роботи сніпетів полягає в тому, що всю сторінку передають під час початкового (тобто не-AJAX) запиту, а потім із кожним AJAX [subrequest |components#Signal] (запит до того самого подання того самого презентера) тільки код змінених частин передають до сховища `payload`, згаданого раніше.
70+
71+
Сніпети можуть нагадати вам Hotwire для Ruby on Rails або Symfony UX Turbo, але Nette придумав їх чотирнадцятьма роками раніше.
72+
73+
74+
Інвалідація .[#toc-invalidation-of-snippets]
75+
============================================
76+
77+
Кожен нащадок класу [Control |components] (яким є і Presenter) здатний пам'ятати, чи були якісь зміни під час запиту, що вимагають повторного відображення. Існує кілька способів впоратися з цим: `redrawControl()` і `isControlInvalid()`. Приклад:
78+
79+
```php
80+
public function handleLogin(string $user): void
81+
{
82+
// Об'єкт має повторно відображатися після того, як користувач увійшов у систему
83+
$this->redrawControl();
84+
// ...
85+
}
86+
```
87+
Однак Nette забезпечує ще більш тонкий дозвіл, ніж цілі компоненти. Перераховані методи приймають ім'я так званого "фрагмента" як необов'язковий параметр. "Фрагмет" це, по суті, елемент у вашому шаблоні, позначений для цієї мети макросом Latte, докладніше про це пізніше. Таким чином, можна попросити компонент перемалювати тільки *частину* свого шаблону. Якщо весь компонент недійсний, то всі його фрагменти відображаються заново. Компонент є "недійсним", якщо будь-який з його субкомпонентів є недійсним.
88+
89+
```php
90+
$this->isControlInvalid(); // -> false
91+
92+
$this->redrawControl('header'); // анулює фрагмент з ім'ям 'header'
93+
$this->isControlInvalid('header'); // -> true
94+
$this->isControlInvalid('footer'); // -> false
95+
$this->isControlInvalid(); // -> true, принаймні один фрагмент недійсний
96+
97+
$this->redrawControl(); // робить недійсним весь компонент, кожен фрагмент
98+
$this->isControlInvalid('footer'); // -> true
99+
```
100+
101+
Компонент, який отримав сигнал, автоматично позначається для перемальовування.
102+
103+
Завдяки перемальовуванню фрагментів ми точно знаємо, які частини яких елементів мають бути перемальовані.
104+
105+
106+
Тег `{snippet} … {/snippet}` .{toc: Tag snippet}
107+
================================================
108+
109+
Рендеринг сторінки відбувається так само, як і під час звичайного запиту: завантажуються одні й ті самі шаблони тощо. Однак найважливіше - це не допустити потрапляння до вихідного сигналу тих частин, які не повинні потрапити до вихідного сигналу; інші частини мають бути пов'язані з ідентифікатором і надіслані користувачеві у форматі, зрозумілому для обробника JavaScript.
110+
111+
112+
Синтаксис .[#toc-sintaksis]
113+
---------------------------
114+
115+
Якщо в шаблоні є елемент управління або фрагмент, ми повинні обернути його за допомогою парного тега `{snippet} ... {/snippet}` - відмальований фрагмент буде "вирізаний" і відправиться в браузер. Він також укладе його в допоміжний тег `<div>` (можна використовувати інший). У наступному прикладі визначено сніппет з ім'ям `header`. Він також може являти собою шаблон компонента:
116+
117+
```latte
118+
{snippet header}
119+
<h1>Hello ... </h1>
120+
{/snippet}
121+
```
122+
123+
Якщо ви хочете створити сніппет з іншим елементом, що містить, відмінним від `<div>`, або додати користувацькі атрибути до елемента, ви можете використовувати таке визначення:
124+
125+
```latte
126+
<article n:snippet="header" class="foo bar">
127+
<h1>Hello ... </h1>
128+
</article>
129+
```
130+
131+
132+
Динамічні сніпети .[#toc-dinamiceskie-snippety]
133+
===============================================
134+
135+
У Nette ви також можете визначити сніпети з динамічним ім'ям, заснованим на параметрі часу виконання. Це найбільше підходить для різних списків, де нам потрібно змінити лише один рядок, але ми не хочемо переносити весь список разом із ним. Прикладом цього може бути:
136+
137+
```latte
138+
<ul n:snippet="itemsContainer">
139+
{foreach $list as $id => $item}
140+
<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">обновить</a></li>
141+
{/foreach}
142+
</ul>
143+
```
144+
145+
Існує один статичний сніппет `itemsContainer`, що містить кілька динамічних сніпетів: `пункт-0`, `пункт-1` і так далі.
146+
147+
Ви не можете перемалювати динамічний фрагмент безпосередньо (перемальовування `item-1` не має ефекту), ви маєте перемалювати його батьківський фрагмент (у цьому прикладі `itemsContainer`). При цьому виконується код батьківського сніпета, але браузеру передаються тільки його вкладені сніпети. Якщо ви хочете передати тільки один із вкладених сніпетів, вам потрібно змінити введення для батьківського сніпета, щоб не генерувати інші вкладені сніпети.
148+
149+
У наведеному прикладі необхідно переконатися, що під час AJAX-запиту до масиву `$list` буде додано тільки один елемент, тому цикл `foreach` виводитиме тільки один динамічний фрагмент.
150+
151+
```php
152+
class HomepagePresenter extends Nette\Application\UI\Presenter
153+
{
154+
/**
155+
* Этот метод возвращает данные для списка.
156+
* Обычно это просто запрос данных из модели.
157+
* Для целей этого примера данные жёстко закодированы.
158+
*/
159+
private function getTheWholeList(): array
160+
{
161+
return [
162+
'First',
163+
'Second',
164+
'Third',
165+
];
166+
}
167+
168+
public function renderDefault(): void
169+
{
170+
if (!isset($this->template->list)) {
171+
$this->template->list = $this->getTheWholeList();
172+
}
173+
}
174+
175+
public function handleUpdate(int $id): void
176+
{
177+
$this->template->list = $this->isAjax()
178+
? []
179+
: $this->getTheWholeList();
180+
$this->template->list[$id] = 'Updated item';
181+
$this->redrawControl('itemsContainer');
182+
}
183+
}
184+
```
185+
186+
187+
Сніпети в увімкненому шаблоні .[#toc-snippety-vo-vklyucennom-sablone]
188+
=====================================================================
189+
190+
Може трапитися так, що сніппет міститься в шаблоні, який вмикається з іншого шаблону. У цьому разі необхідно обернути код включення в другому шаблоні макросом `snippetArea`, потім перемалювати як snippetArea, так і сам сніппет.
191+
192+
Макрос `snippetArea` гарантує, що код усередині нього буде виконано, але браузеру буде надіслано тільки фактичний фрагмент включеного шаблону.
193+
194+
```latte
195+
{* parent.latte *}
196+
{snippetArea wrapper}
197+
{include 'child.latte'}
198+
{/snippetArea}
199+
```
200+
```latte
201+
{* child.latte *}
202+
{snippet item}
203+
...
204+
{/snippet}
205+
```
206+
```php
207+
$this->redrawControl('wrapper');
208+
$this->redrawControl('item');
209+
```
210+
211+
Ви також можете поєднувати його з динамічними сніпетами.
212+
213+
214+
Додавання та видалення .[#toc-dobavlenie-i-udalenie]
215+
====================================================
216+
217+
Якщо додати новий елемент у список і анулювати `itemsContainer`, AJAX-запит поверне фрагменти, включно з новим, але javascript-обробник не зможе його відобразити. Це відбувається тому, що немає HTML-елемента з новоствореним ID.
218+
219+
У цьому випадку найпростіший спосіб - обернути весь список у ще один сніпет і визнати його недійсним:
220+
221+
```latte
222+
{snippet wholeList}
223+
<ul n:snippet="itemsContainer">
224+
{foreach $list as $id => $item}
225+
<li n:snippet="item-$id">{$item} <a class="ajax" n:href="update! $id">обновить</a></li>
226+
{/foreach}
227+
</ul>
228+
{/snippet}
229+
<a class="ajax" n:href="add!">Добавить</a>
230+
```
231+
232+
```php
233+
public function handleAdd(): void
234+
{
235+
$this->template->list = $this->getTheWholeList();
236+
$this->template->list[] = 'New one';
237+
$this->redrawControl('wholeList');
238+
}
239+
```
240+
241+
Те ж саме стосується і видалення елемента. Можна було б надіслати порожній сніппет, але зазвичай списки можуть бути посторінковими, і було б складно реалізувати видалення одного елемента і завантаження іншого (який раніше перебував на іншій сторінці посторінкового списку).
242+
243+
244+
Надсилання параметрів компоненту .[#toc-otpravka-parametrov-komponentu]
245+
=======================================================================
246+
247+
Коли ми надсилаємо параметри компоненту через AJAX-запит, чи то сигнальні, чи постійні параметри, ми повинні надати їхнє глобальне ім'я, яке також містить ім'я компонента. Повне ім'я параметра повертає метод `getParameterId()`.
248+
249+
```js
250+
$.getJSON(
251+
{link changeCountBasket!},
252+
{
253+
{$control->getParameterId('id')}: id,
254+
{$control->getParameterId('count')}: count
255+
}
256+
});
257+
```
258+
259+
І обробити метод з відповідними параметрами в компоненті.
260+
261+
```php
262+
public function handleChangeCountBasket(int $id, int $count): void
263+
{
264+
265+
}
266+
```

0 commit comments

Comments
 (0)