- vừa được xem lúc

Hướng dẫn FormType trong PHP Symfony - Nested form (Allowing "new/remove" Tags with the "Prototype") phần 2

0 0 53

Người đăng: P Griffin

Theo Viblo Asia

Giới Thiệu

Xin chào các bạn, hôm trước mình đã hướng dẫn các bạn làm thế nào để hiển thị 1 form collection type lên màn hình hôm nay mình sẽ tiếp tục hướng dẫn các bạn làm thế nào để có thể thêm mới hay xoá đi tag form trong collection type, trong bài hướng dẫn này chúng ta sẽ cần 1 ít Javascript để thực hiện việc thêm mới hay xoá đi, mình sẽ sử dụng tiếp ví dụ ở bài trước ở bài trước ...

Nested form (CollectionType Field)

Trước tiên chúng ta hãy mở lại TaskType.php và thêm vào option là allow_add cái option allow_add sẽ render ra code kiểu html của type TagType:

public function buildForm(FormBuilderInterface $builder, array $options): void
{ $builder->add('tags', CollectionType::class, [ 'entry_type' => TagType::class, 'entry_options' => ['label' => false], 'allow_add' => true, ]);
}

Ok bây giờ chúng ta sẽ quay sang file template add thêm attribute data-prototype vào thẻ <ul>, như ví dụ ở đây mình sử dụng thẻ <ul> vì nó là thẻ chứa toàn bộ các tag con bên trong đó thực ra các bạn chỉ cần đặt data-prototype lên thẻ cha mà chứa toàn bộ các tag con bên trong đó là được

<ul class="tags" data-prototype="{{ form_widget(form.tags.vars.prototype)|e('html_attr') }}"></ul>

và add thêm 1 button để khi click thì sẽ add thêm 1 tag nữa:

<button type="button" class="add_item_link" data-collection-holder-class="tags">Add a tag</button>

Đến đây các bạn sẽ thắc mắc là làm sao để khi click vào button Add a tag thì làm sao mà nó có thể tự sinh ra 1 tag mới ? ? Nếu các bạn chạy lên trình duyệt bật F12 ở chỗ các bạn add data-prototype cho <ul> các bạn sẽ thấy nó render ra html nhiệm vụ của chúng ta bây giờ là:

  • Dùng JS copy cái nội dung trong data-prototype đó và add thêm tag vào <ul>
  • Thay thế __name__ thành 1 cái tên duy nhất (không bị trùng lặp) trong <ul>
<ul class="tags" data-prototype="&lt;div&gt;&lt;label class=&quot; required&quot;&gt;__name__&lt;/label&gt;&lt;div id=&quot;task_tags___name__&quot;&gt;&lt;div&gt;&lt;label for=&quot;task_tags___name___name&quot; class=&quot; required&quot;&gt;Name&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;task_tags___name___name&quot; name=&quot;task[tags][__name__][name]&quot; required=&quot;required&quot; maxlength=&quot;255&quot; /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;">

Để copy cái nội dung trong data-prototype và thay thế __name__ chúng ta sẽ sử dụng JS và làm như sau:

jQuery(document).ready(function() { var $tagsCollectionHolder = $('ul.tags'); $tagsCollectionHolder.data('index', $tagsCollectionHolder.find('input').length); $('body').on('click', '.add_item_link', function(e) { var $collectionHolderClass = $(e.currentTarget).data('collectionHolderClass'); addFormToCollection($collectionHolderClass); })
});
function addFormToCollection($collectionHolderClass) { var $collectionHolder = $('.' + $collectionHolderClass); var prototype = $collectionHolder.data('prototype'); var index = $collectionHolder.data('index'); var newForm = prototype; newForm = newForm.replace(/__name__/g, index); $collectionHolder.data('index', index + 1); var $newFormLi = $('<li></li>').append(newForm); $collectionHolder.append($newFormLi)
}

Rồi bây giờ trên trình duyệt nếu chúng ta click và button Add a tag thì 1 tag con sẽ được tự động thêm vào <ul> Bây giờ chúng ta sẽ phải làm cách nào để xoá/remove đi cái tag mà chúng ta vừa mới thêm vào lúc nãy. Chúng ta mở lại file TaskType.php và add thêm option allow_delete:

public function buildForm(FormBuilderInterface $builder, array $options): void
{ $builder->add('tags', CollectionType::class, [ 'allow_delete' => true, ]);
}

Chúng ta quay sang file template và add thêm JS xử lý xoá tag trong <ul> như sau:

jQuery(document).ready(function() { $collectionHolder = $('ul.tags'); $collectionHolder.find('li').each(function() { addTagFormDeleteLink($(this)); });
}); function addTagFormDeleteLink($tagFormLi) { var $removeFormButton = $('<button type="button">Delete this tag</button>'); $tagFormLi.append($removeFormButton); $removeFormButton.on('click', function(e) { $tagFormLi.remove(); });
}

Như vậy là chúng ta đã có thể thêm/xoá tag trong <ul> mà chúng ta muốn cũng rất đơn giản đúng không nào.

Kết luận

Với việc chúng ta có thểm thêm/xoá các nội dung của 1 form con chứa trong 1 form lớn chúng ta có thể dễ dàng thay đổi nội dung của form để lưu lại dữ liệu mà chúng ta mong muốn.

Tham khảo

https://symfony.com/doc/current/form/form_collections.html

Bình luận