how to use tagify js with laravel livewire

We are going to build a Livewire component using tagify library.

tagify is a javascript library with a lot of features to make a tag input like this:

the goal is to create a livewire component to interact with this library.

Install Livewire

First, install Livewrie in your Laravel project

composer require livewire/livewire

then create a blade file and include tagify and livewire.


<html>
<head>
    <script src="https://cdn.jsdeivr.net/npm/@yaireo/tagify"></script>
    <script src="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.polyfills.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.css" rel="stylesheet" type="text/css" />

    @livewireStyles

</head>
<body>
 

@livewireScripts

 </body>
</html>

the basic way to use Tagify with vanilla javascript is to create a new object and pass the element to the object like this:

HTML:

<input name="tags" type="text" id="tags">

Javascript:

 var input = document.querySelector('input#tags');
 tagify = new Tagify(input);

and if we want it to have existing tags we can use addtags() method:

tagify.addTags(['laravel','Vue','React','PHP']);

now we want to do these things with a livewire component.

we should write something like this and get the same results.

@livewire('tagify',['tags' => ['php','laravel','livewire','javascript']])

Create a Livewire Component

create a component with make:livewire artisan command.

php artisan make:liverwire Tagify

this will create a blade file in “resources/views/livewire” and a PHP class in “app/Http/Livewire”.

for testing the component we create a route and return a view.

Route::get('/tagify-test',function (){

    return view('tagify-test');

});

in the view, we use the component.

//...    
 
</head>

<body>
@livewire('tagify')


 
</body>

in the component, we create an input to show tags in it.

if we were using javascript we did something like this:

<input name='tags' >
 var input = document.querySelector('input[name=tags]');

 new Tagify(input)

but in a livewire component we can’t just use vanilla javascript like this. we have to use Alpinejs library. a very simple and small js library that works with livewire.

first we have to include Alpinejs.

    <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>

now we have to do what we did in js with Alpine.

in pure javascript, we did two things:

1-we selected the input we needed.

2-we initialized a Tag class on that input.

we just need to figure this out in Alpinejs.

in the livewire component, we need to select the current component. there is an attribute named “x-ref”

we can use it to reference the input so first add x-ref to the input:

<div>

    <input

        x-ref="input"   
        type="text"
        
    >


</div>

x-ref="input" means that we can refer to this component with Alpinejs with $refs.input

$refs is a property in Alpine we can use to get DOM elements.

so now we figured out how to retrieve this element. we need to initialize the Tagify Class.

we use x-init for this. x-init is a directive that can be used to run javascript code when the element is initialized.

write the initialization code in x-init:

<div>

    <input    
        x-ref="input"
        x-init="new Tagify($refs.input)"
        type="text"
       >
</div>

we initialized a Tagify class and for the argument we passed the element by using $refs.input.

the last thing we have to add to this component is a directive called x-data,

in Alpinejs x-data is a directive that makes the component reactivity possible. for the time being, we just need to use it and leave it empty here. because if we don’t we will encounter a console error:

<div>

    <input    
        x-data='{}'
        x-ref="input"
        x-init="new Tagify($refs.input)"
        type="text"
       >
</div>

now the input should work. we just need to use it in a blade file:

 @livewire('tagify')

now the simplest form of the component is ready. but we need to add the capability to show default tags.

Showing Default Tags

for doing this tagify library uses “value” attribute like this:

<input type="text" value="PHP,Livewire,Laravel" />

tags are comma-separated here. we can do just that and add a value attribute.

I think for our component it’s better to get the tags as an array. something like this:

@livewire('tagify',['tags' => ['php','laravel','javascript','livewire']])

first, we have to convert the comma-seperated string into an array.

in the Tagify component class add a $tags property

class Tagify extends Component{    
public $tags=[];
//... 
}

since tagify uses comma-separate string as a default value we have to convert it to an array that we get from the component.

to do that we use the mount method on the component class.

class Tagify extends Component{   
 public $tags = [];     
 public function mount()    
 {        
 $this->fill(['tags' => implode(',', $this->tags)]);    
 }    
 public function render()    
 {        
 return view('livewire.tagify');    
 }

}

in the mount() method we use fill() to get the $tags property and convert it to a comma-separated string.

and the component view will be like this:

<div>    
   <input        
           x-data="{  }"       
           x-ref="input"       
           x-init="new Tagify($refs.input)"        
           type="text"        
           value="{{$tags}}"    
    >  
</div>

now in the view code, we use the component.

we just need to pass an array to the component to have default tags in the input.

@livewire('tagify',['tags' => ['PHP','Laravel','HTML','Livewire']])

Create a Suggestion List

for the final feature, we are going to create a suggestion list for the component to select tags.

the usual javascript usage is like this.

HTML:

<input type="text" id="tags">

Javascript:

    var input = document.querySelector('input#tags');

    var tagify = new Tagify(input,{
    whitelist:['PHP','Laravel','Livewire','Javascript',],
        dropdown: {
            classname: "tag-dropdown",
            enabled: 0,             // show suggestions on focus
            closeOnSelect: false    //  don't hide the dropdown when an item is selected
        }


    });

the “classname” can be used to style the dropdown.

now let’s implement this in the livewire component.

we add the parameters inside the component.

<div>

    <input


        x-data="{ }"
        x-ref="input"
        x-init="new Tagify($refs.input,{
        whitelist:{{json_encode($suggestions)}},
         dropdown: {
       
          classname: 'tag-dropdown',
          enabled: 0, // show suggestions on focus
          closeOnSelect: false // don't hide the dropdown when an item is selected
         }

    })"
        type="text"
        value="{{$tags }}"
 

    >


</div>

we add the “whitelist” and “dropdown” parameters just like the javascript version with one difference.

we pass the $suggestions as a JSON variable.

in the component class add a $suggestions property and set the default to an empty array(to be an optional parameter).

namespace App\Http\Livewire;

use Livewire\Component;

class Tagify extends Component
{

    public $tags = [];
    public $suggestions = [];

    public function mount()
    {

        $this->fill(
            [
                'tags' => implode(',', $this->tags),
                'suggestions' => $this->suggestions
            ],
        );
    }

    public function render()
    {


        return view('livewire.tagify');
    }
}

if we use the “suggestions” in the “tagify” component. a dropdown will be shown on click.

@livewire('tagify',['suggestions' => ['Amazon','Alibaba','Netflix','Facebook']])

we can build a lot of more features for this component but i think this is good enough for an example.

you can try to add to it by reading tagify and livewire documentation.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *