Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to using in livewire #789

Open
Saeeed-B opened this issue Jun 26, 2021 · 5 comments
Open

How to using in livewire #789

Saeeed-B opened this issue Jun 26, 2021 · 5 comments
Labels

Comments

@Saeeed-B
Copy link

@JiHong88 hi.
How to using with livewire framework?
How to use wire:model?
With Ex please.

@JiHong88
Copy link
Owner

@Saeeed-B Sorry, I don't know well of the livewire framework. :(

@kaju74
Copy link

kaju74 commented May 5, 2022

Are u still interested in how to use SunEditor with Livewire & Alpine.JS? I've implemented this just a few days ago and it work's like a charme until now 8-) Could write a possible solution on interest...

@JiHong88
Copy link
Owner

JiHong88 commented May 5, 2022

Absolutely! I think it would be very good.

@kaju74
Copy link

kaju74 commented May 9, 2022

Okay, here we go 8-)

In our Livewire component, we need a public variable to store the content. This could be a 'normal' string variable or an eloquent field from our model (e.g. public Post $post;). Make sure you include this field in the validation rules() of the livewire component to get the form attributes after submitting it (e.g. $attributes = $this->getValidatedAttributes()). Take a look at the livewire documentation if you're not familiar with this form processing stuff.

To be able to use the SunEditor in our form, the easiest way is to create a blade component for this. This component can then be used in our Livewire blade template as usual:

<x-suneditor wire:model.defer="post.description">
    My post content
</x-suneditor>

Use the "defer" directive to get rid of unneccessary server calls.

Now we take a look at our blade component. To be able to use multiple SunEditor's in one form, we first need to create unique names for all instances. The simpliest way is to include a small php call in our blade component for this:

@php
    $name = $attributes->wire('model')->value();
@endphp

The $name variable includes now the name of the linked wire model (i.e. "post.description") and can be used for the textarea and an optional html label tag:

<textarea x-data="editor($el, @entangle($attributes->wire('model')))" name="{{ $name }}" x-cloak></textarea>
<label for="{{ $name }}">
    {{ $slot }}:
</label>

The "$slot" will be replaced with our content above ("My post content") and is used for the textarea label. The textarea itself injects Alpine.js via the "x-data" directive and uses the "@entangle" keyword to 2-way-link Alpine with our Livewire model. The "x-cloak" custom html attribute is used to hide the textarea while loading the content. It's defined in the "app.css" file of our Laravel application:

/**
 * Alpine.js styling.
 */
[x-cloak] {
    visibility: hidden;
    overflow: hidden;
    display: none;
}

I always try to separate larger Alpine.js logic from my blade components, so I call the "editor" function which code is placed in it's own file. So let's take a look at the "app.js" file of our app first:

/**
 * Alpine.js library.
 *
 * You can find the documentation here:
 * https://github.com/alpinejs/alpine
 */
import Alpine from 'alpinejs';

// set alpine available via global window
window.Alpine = Alpine;

// inject custom components
require('./components/suneditor');

// start it!
Alpine.start();

We include the SunEditor functionality by 'require'-ing the separate Javascript file (suneditor.js) in the 'components'-subfolder:

import SunEditor from "suneditor";
import {align, blockquote, fontColor, hiliteColor, list, table, link} from 'suneditor/src/plugins'

document.addEventListener('alpine:init', () => {
    Alpine.data('editor', (el, model) => ({
        value: model,
        init() {
            let parent = this;

            let editor = SunEditor.create(el, {
                value: this.value,
                plugins: [align, blockquote, fontColor, hiliteColor, list, table, link],
                buttonList: [
                    ...
                ],
            });

            editor.onChange = function (contents) {
                parent.value = contents;
            }
        }
    }))
})

First, we need to make sure that Alpine.js has finished it's initialization stuff. Then we define our 'editor'-function with accepts just two parameters: "el" and "model". The "el" passes the textarea element from the dom to be used and the "model" holds the Livewire model defined. Then we create a new SunEditor instance with the plugins to use (and some other stuff you need). To fill the editor with the previously stored content, we only need to set the 'value' variable. To update the wire model, we hook into the "onChange" callback from SunEditor. At this point, we just fill the value with the new content - that's it.

JiHong88 added a commit that referenced this issue May 10, 2022
@Saeeed-B
Copy link
Author

Saeeed-B commented Jun 5, 2022

i use like this:

 const editor = SUNEDITOR.create();
  editor.onChange = function (contents, core) {
      @this.set('Content', core);
  }

this is very simple and apline is not required

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants