Giriş yapmadınız.

Duyuru

TÜRKÇE KİTAP DUYURUSU:
Laravel 5 : Laravel 5.1 Güzelliği (Türkçe)
Vue.js 2 : Vue.js 2 Majesteleri (Türkçe)

#1 25.09.2018 08:47:25

magarex
Üye
Kayıtlı: 05.09.2017
Mesajlar: 43

Jquery Nestable

https://dbushell.com/Nestable/    bu eklentiyi projeme dahil ettim..

Bu şekilde drag drop ile kullanıcı istediği şekilde düzenleyecek ve örneğin kategori ekleyecek sadece tek input var kategori ekle inputu ekleyince buraya düşecek.. Burada drag drop ile alt alta iç içe yapıp kaydete basacak. ve kaydettiği şekil aynen kalması gerekli..
Bu plugin şöyle bir veri veriyor her kaydedilişte
[{"id":1},{"id":2,"children":[{"id":3},{"id":4},{"id":5,"children":[{"id":6},{"id":7},{"id":8}]},{"id":9},{"id":10}]},{"id":11},{"id":12}]

ben bu veriyi nasıl bir tablo oluşturmalıyım ve nasıl kaydedip çekmeliyim

Çevrimdışı

#2 25.09.2018 09:01:16

mgsmus
Moderatör
Yer: Mersin
Kayıtlı: 17.08.2013
Mesajlar: 1,252
Website

Yanıt: Jquery Nestable

Öncelikle o plugini değil şu plugini kullanıyorsunuz:
https://github.com/ilikenwf/nestedSortable

Ötekisi eski ve bu tavsiye ettiğim işimize yarayacak birkaç özelliğe sahip. Ayrıca aktif diyebiliriz.
Görsel tasarıma bakmayın, hepsinin yaptığı aynı. Kendi ihtiyacınıza göre değiştirebilirsiniz.

Demo için:
http://ilikenwf.github.io/example.html

Öncelikle işlem yaptığımız modelin Category olduğunu varsayıyorum. Alanlar da id(primary), parent_id(int), depth(int) ve name(varchar)
Bu yapı adjacency list olarak adlandırılıyor. Araştırma yapabilirsiniz. depth alanıda derinlik değerini tutacağız. Bazı işlemler yaparken işinize yardımcı olacaktır.
Derinlik şu şekilde değer alıyor:

Kategori 0
    Alt Kategori 1
    Alt Kategori 1
        Alt Kategori 2
    Alt Kategori 1

nestedSortable plugininin toArray şeklinde işimizi çok kolaylaştıracak bir yöntemi var:

var data = $('ol.sortable').nestedSortable('toArray', {startDepthCount: 0});

Bu bize şöyle bir çıktı verecek:

[
    {"id":null,"parent_id":null,"depth":0,"left":1,"right":14},
    {"id":"2","parent_id":null,"depth":1,"left":2,"right":9},
    {"id":"4","parent_id":"2","depth":2,"left":3,"right":6},
    {"id":"6","parent_id":"4","depth":3,"left":4,"right":5},
    {"id":"5","parent_id":"2","depth":2,"left":7,"right":8},
    {"id":"7","parent_id":null,"depth":1,"left":10,"right":11},
    {"id":"3","parent_id":null,"depth":1,"left":12,"right":13}
]

Biz bu JSON veriyi PHP içinde json_decode($json, true) şeklinde diziye çevirdiğimizde şöyle bir PHP dizisi elde etmiş olacağız:

Array
(
    [0] => Array
        (
            [id] =>
            [parent_id] =>
            [depth] => 0
            [left] => 1
            [right] => 14
        )

    [1] => Array
        (
            [id] => 2
            [parent_id] =>
            [depth] => 1
            [left] => 2
            [right] => 9
        )

    [2] => Array
        (
            [id] => 4
            [parent_id] => 2
            [depth] => 2
            [left] => 3
            [right] => 6
        )

    [3] => Array
        (
            [id] => 6
            [parent_id] => 4
            [depth] => 3
            [left] => 4
            [right] => 5
        )

    [4] => Array
        (
            [id] => 5
            [parent_id] => 2
            [depth] => 2
            [left] => 7
            [right] => 8
        )

    [5] => Array
        (
            [id] => 7
            [parent_id] =>
            [depth] => 1
            [left] => 10
            [right] => 11
        )

    [6] => Array
        (
            [id] => 3
            [parent_id] =>
            [depth] => 1
            [left] => 12
            [right] => 13
        )

)

Burada left, right değerleri işimize yaramıyor. Bu değerler nested set modeli için. Bizim model adjacency olduğu için gerek yok.


Şimdi gelelim veritabanından gelen veri ile nestedSortable oluşturmaya.
nestedSortable için temel HTML yapısını verebilen şöyle bir sınıf hazırladım:

class NestedSortable
{
    public function build($items, $parentId = null, & $i = 0)
    {
        $result = null;

        $i = count($items);

        foreach ($items as $item) {
            if ($item->parent_id == $parentId) {

                // Burada item_1 gibi li elementine kategori id'sini yazdırıyoruz.
                // nestedSortable kaynağına baktım. Bu şekilde id'yi alıp hiyerarşiyi oluşturuyor. Yani gerekli.
                $result .= '<li id="item_'.$item->id.'">';

                // Burada data-name ile kategori adının nestedSortable'nin toArray yöntemiyle
                // elde edilen çıktıya name anahtarı dahil edilmesini sağlıyoruz.
                // Kaynak koduna baktım, li içinde div elementinin data-* değerlerini dahil ediyor.
                // Yani siz buraya ekleme yapabilirsiniz.
                $result .= '<div data-name="'.$item->name.'">' . $item->name . '</div>';

                $result .= $this->build($items, $item->id, $i);
                $result .= '</li>';
                $i--;
            }
        }

        $leadClass = $i == 1 ? 'sortable' : null;

        return !is_null($result) ? '<ol class="' . $leadClass . '">' . $result . '</ol>' : null;
    }
}

Örneğin:

$categories = Category::all();

$sortableHTML = (new NestedSortable)->build($categories);

Bu bize şöyle bir HTML çıktı veriyor:

<ol class="sortable">
    <li id="item_1">
        <div data-name="Bilgisayar">Bilgisayar</div>
        <ol class="">
            <li id="item_2">
                <div data-name="Dizüstü">Dizüstü</div>
                <ol class="">
                    <li id="item_3">
                        <div data-name="Oyuncu Dizüstü">Oyuncu Dizüstü</div>
                    </li>
                    <li id="item_4">
                        <div data-name="Workstation">Workstation</div>
                    </li>
                </ol>
            </li>
        </ol>
    </li>
</ol>

Plugini de kullandığımızda istediğimiz sonuca ulaşmış oluyoruz:

$('ol.sortable').nestedSortable({
    handle: 'div',
    items: 'li',
    toleranceElement: '> div',

    // İlk element mecburi ama null, bu seçenek onu çıkarmamızı sağlıyor.
    // Karıştırmayın, root element sistem için gerekli, bizim kategorilerimizle ilgisi yok yani
    // Sonuçta ağacın dalları ve yaprakları tutabilmesi için bir başlangıç gövdesi olmak zorunda
    excludeRoot:true
});

Sayfada bir düğme aracılığı ile veriyi ajax ile bir rotaya gönderelim:

<ol class="sortable">
    <li id="item_1">
        <div data-name="Bilgisayar">Bilgisayar</div>
        <ol class="">
            <li id="item_2">
                <div data-name="Dizüstü">Dizüstü</div>
                <ol class="">
                    <li id="item_3">
                        <div data-name="Oyuncu Dizüstü">Oyuncu Dizüstü</div>
                    </li>
                    <li id="item_4">
                        <div data-name="Workstation">Workstation</div>
                    </li>
                </ol>
            </li>
        </ol>
    </li>
</ol>

<button type="button" id="update">Güncelle</button>

<script>
$(function() {

    var $updateBtn = $('#update');

    $('ol.sortable').nestedSortable({
       handle: 'div',
       items: 'li',
       toleranceElement: '> div',
       excludeRoot:true
    });

    $updateBtn.on('click', function() {

        var data = $('ol.sortable').nestedSortable('toArray', {startDepthCount: 0});

        $.ajax({
            url:'/admin/categories/reorder',
            method:'POST',
            data: data,
            success: function(res) {
                alert(res.message);
            }
        });

    });

});
</script>

CategoryController.php:

public function reorder(Request $request)
{
    // nestedSortable'den gelen veriyi diziye çevirelim
    // json_decode'nin 2. parametresi assoc = true json ile gelen objelerin de array olmasını sağlayacak
    // yani tamamen saf bir array elde etmiş olacağız.
    $sortedData = json_decode($request->get('data'), true);

    // Kullanmayacağımız left ve right değerlerini kaldıralım
    foreach($sortedData as & $sorted) {
        unset($sorted['left'], $sorted['right']);
    }

    // Gelen veri zaten tablomuzdaki ile eşdeğer olduğu için hiç zahmete girmeden:
    Category::truncate();
    Category::insert($sortedData);

    return response()->json([
        'message' => 'Güncellendi';
    ]);
}

Ne yazık ki uzun, karışık bir konu ve kendi sisteminize göre bir çok yeri değiştirmeniz gerekebilir.

Çevrimdışı

#4 25.09.2018 10:04:11

mgsmus
Moderatör
Yer: Mersin
Kayıtlı: 17.08.2013
Mesajlar: 1,252
Website

Yanıt: Jquery Nestable

Akşam hazırlamıştım arkadaş konuyu silmiş. Tekrar konu açtırdım, uğraştık bayağı boşa gitmesin smile

Çevrimdışı

#5 25.09.2018 11:17:52

magarex
Üye
Kayıtlı: 05.09.2017
Mesajlar: 43

Yanıt: Jquery Nestable

mgsmus yazdı:

Akşam hazırlamıştım arkadaş konuyu silmiş. Tekrar konu açtırdım, uğraştık bayağı boşa gitmesin smile

Hocam Ellerinize sağlık sayenizde sona doğru yaklaştım şimdi bir sorun var.
Adam kategori ekledi ilk durum view'ımda nasıl olacak ? Adam ekledi ben controllerımda Category::all()
dedim viewa gönderdim şu aşağıdaki şeklin değişmesi gerekiyor elden geçirmek lazım ama çözemedim kafam durdu nasıl olmalı ilk durumda burası ?

<ol class="sortable">
    <li id="item_1">
        <div data-name="Bilgisayar">Bilgisayar</div>
        <ol class="">
            <li id="item_2">
                <div data-name="Dizüstü">Dizüstü</div>
                <ol class="">
                    <li id="item_3">
                        <div data-name="Oyuncu Dizüstü">Oyuncu Dizüstü</div>
                    </li>
                    <li id="item_4">
                        <div data-name="Workstation">Workstation</div>
                    </li>
                </ol>
            </li>
        </ol>
    </li>
</ol>

Çevrimdışı

#6 25.09.2018 12:18:39

mgsmus
Moderatör
Yer: Mersin
Kayıtlı: 17.08.2013
Mesajlar: 1,252
Website

Yanıt: Jquery Nestable

app içerisine Services isimli bir klasör oluşturun. İçine de NestedSortable sınıfını ekleyin:

app/Services/NestedSortable.php

<?php

namespace App\Services;

class NestedSortable
{
// ...


Daha sonra CategoryController.php içinde ya da hangi controller ise:

use App\Services\NestedSortable ;

public function index(NestedSortable $sortableBuilder)
{
    $categories = Category::all();

    $sortableHTML = $sortableBuilder->build($categories);

    return view('categories', compact('categories', 'sortableHTML'));
}

categories.blade.php içerisinde:

<div>
    {!! $sortableHTML !!}
</div>

Ayrı bir sayfada kategori ekletip bu sayfaya yönlendirdiniz mi yeni kategorileri görür.
Yeni kategori eklettiğiniz sayfada parent_id seçilmesine izin verirseniz kategoriyi sonra taşımadan direk istenen yere ekletebilirsiniz.

Çevrimdışı

#7 25.09.2018 12:23:52

magarex
Üye
Kayıtlı: 05.09.2017
Mesajlar: 43

Yanıt: Jquery Nestable

mgsmus yazdı:

app içerisine Services isimli bir klasör oluşturun. İçine de NestedSortable sınıfını ekleyin:

app/Services/NestedSortable.php

<?php

namespace App\Services;

class NestedSortable
{
// ...


Daha sonra CategoryController.php içinde ya da hangi controller ise:

use App\Services\NestedSortable ;

public function index(NestedSortable $sortableBuilder)
{
    $categories = Category::all();

    $sortableHTML = $sortableBuilder->build($categories);

    return view('categories', compact('categories', 'sortableHTML'));
}

categories.blade.php içerisinde:

<div>
    {!! $sortableHTML !!}
</div>

Ayrı bir sayfada kategori ekletip bu sayfaya yönlendirdiniz mi yeni kategorileri görür.
Yeni kategori eklettiğiniz sayfada parent_id seçilmesine izin verirseniz kategoriyi sonra taşımadan direk istenen yere ekletebilirsiniz.

Hocam dediğiniz şekilde yaptığımda sortable disabled oluyor sanırım drag drop olayı iptal oluyor bu neden olur fikriniz var mı ?

Çevrimdışı

#8 25.09.2018 12:39:07

mgsmus
Moderatör
Yer: Mersin
Kayıtlı: 17.08.2013
Mesajlar: 1,252
Website

Yanıt: Jquery Nestable

Javascript konsoluna bakın hata veriyor mu diye. Hata vermiyorsa sebebini bilmem mümkün değil.

Çevrimdışı

#9 25.09.2018 12:42:00

magarex
Üye
Kayıtlı: 05.09.2017
Mesajlar: 43

Yanıt: Jquery Nestable

mgsmus yazdı:

Javascript konsoluna bakın hata veriyor mu diye. Hata vermiyorsa sebebini bilmem mümkün değil.

$leadClass = $i == 1 ? 'sortable' : null;

        return !is_null($result) ? '<ol class="sortable">' . $result . '</ol>' : null;


burayı bu şekilde düzeltince sorunda ortadan kalktı herşey için çok teşekkür ederim.

Çevrimdışı

Forum alt kısmı