I was wondering if anyone has had any luck in implementing the Select2 jQuery library with Laravel to add items dynamically not in the database.
My use case is that I have a list of items that I pull from the database (which I'm using Select2 on that select field), but if an item they are looking for is not there, they should be able to add a new value dynamically and populate it in the database for later use.
I notice that the Select2 library has createSearchChoice callback that I can use, but I'm not exactly sure how to use it to populate items in the database (I'm not sure of the server side logic for it). Anyway, I was wondering if anyone in the Laravel community has done this, or used a different and probably better method to do it.
I thought about just making a separate text field in the form where it could be added, but that seems inconvenient. If anyone has any thoughts or ideas, that would be great. Thank you.
Yeah, that's definitely good for client side, but what is the best way to handle the new data server side?
A simple webapp built in Laravel 5 Fundamentals series uses Select2 to add/create article tags. Watch it from episode 21 and it should answer your question.
Xum, I've actually watched all these videos, but he only manually adds the tags into the database using Tinker. Never through the web interface (he never creates one). Even still, I have everything setup for tags, the relationships and the pivot table, and in the interface I can add the tags like that to articles, but if I want to make tags from Select2, I have no backend logic to handle the new tag being created (it throws an error when the tag doesn't exist). That's actually what I was asking for direction on. I was wondering if anyone has ever added the backend logic for adding tags to the database on the fly using Select2, or some other method, and if anyone had a good solution for doing so.
Actually, thanks to Jammyman1 in the comments section of those videos, he posted a pretty good solution.
The Select 2 options are:
$('#tag_list').select2({
placeholder: "Select or add tags",
tags: true,
tokenSeparators: [",", " "],
createTag: function(newTag) {
return {
id: 'new:' + newTag.term,
text: newTag.term + ' (new)'
};
}
});
And then I added a new function in the controller and called it:
private function syncTags($article, $request)
{
if ( ! $request->has('tag_list'))
{
$article->tags()->detach();
return;
}
$allTagIds = array();
foreach ($request->tag_list as $tagId)
{
if (substr($tagId, 0, 4) == 'new:')
{
$newTag = Tag::create(['name' => substr($tagId, 4)]);
$allTagIds[] = $newTag->id;
continue;
}
$allTagIds[] = $tagId;
}
$article->tags()->sync($allTagIds);
}
It seems to have a few small issues that I'm working through, but so far it's done the trick.
Yelldon said:
Actually, thanks to Jammyman1 in the comments section of those videos, he posted a pretty good solution.
The Select 2 options are:
$('#tag_list').select2({ placeholder: "Select or add tags", tags: true, tokenSeparators: [",", " "], createTag: function(newTag) { return { id: 'new:' + newTag.term, text: newTag.term + ' (new)' }; } });
And then I added a new function in the controller and called it:
private function syncTags($article, $request) { if ( ! $request->has('tag_list')) { $article->tags()->detach(); return; } $allTagIds = array(); foreach ($request->tag_list as $tagId) { if (substr($tagId, 0, 4) == 'new:') { $newTag = Tag::create(['name' => substr($tagId, 4)]); $allTagIds[] = $newTag->id; continue; } $allTagIds[] = $tagId; } $article->tags()->sync($allTagIds); }
It seems to have a few small issues that I'm working through, but so far it's done the trick.
Where exactly did you add in the second part of the code? Was it inside the existing articles controller, or where?
What if I want to use Select2 plugin as single selection and if validation of new value has-error, how can I put that value at the beginning of the select list, or remain selected when retrieved from request::old('tag_id') to data variable?
Now I get old data like so:
var valueID = '{{ Request::old('place_id') }}';
var valueText = '{{ substr(Request::old('place_id'),4) }}';
....
data: [{ id: valueID, text: valueText }],
...
How can I insert data value first in the select list?
Hey guys,
This is my solution, which may help someone looking for it.
I tried the above stuff and it was quite buggy so I thought I'd try something a little different. I have included ->user_id because I want my users to use their own tags, but you can remove that bit and rewrite the checks to Tag::where().
private function syncTags($expense, $tags)
{
$fresh = [];
foreach( $tags as $tag )
{
if( Tag::find($tag) )
{
$fresh[] = $tag;
}
elseif( Auth::User()->tags()->where('name',$tag)->exists() )
{
$fresh[] = Auth::User()->tags()->where('name',$tag)->latest()->first()->id;
}
else
{
$t = new Tag;
$t->user_id = Auth::Id();
$t->name = $tag;
$t->save();
$fresh[] = $t->id;
}
}
$expense->tags()->sync( $fresh );
}
Step 1: Checks if we've been passed an ID
Step 2: If not, check whether we have been passed a name that we already have
Step 3: Finally, if none of those, make a new one and grab its ID
It may look a little bit messy currently and I'm sure this could be tidied up with someone who knows code better than myself
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community