vendredi 22 juillet 2016

Integrating Typeahead JS with laravel-messenger (package) in Laravel 5

Before I begin pasting code, allow me to give you a bit of a background story because it is necessary.

I am using Laravel Messenger: http://ift.tt/1vax87u in my app which offers a nice private messaging system between users.

The problem is, the author of that package displays ALL the users with a checkbox each next to it, so you can select the recipient(s) of your message.

Like this

@if($users->count() > 0)
   <div class="checkbox">
       @foreach($users as $user)
              <label title="{!!$user->name!!}"><input type="checkbox" name="recipients[]" value="{!!$user->id!!}">{!!$user->name!!}</label>
      @endforeach
   </div>
@endif

At this point, if I check a box and send that user a message, 2 records get created in the participants table. One with my user ID and another row with the recipient's user ID along with the thread_id for each row.

While this is fine, it gets cumbersome if I have thousands of users in my database and it would not be ideal for users to go through all the checkboxes to find that one user they wanna send a message to.

So I decided to remove all that and integrate Typeahead JS: http://ift.tt/1pQmP4C

Before I show you the code of Typeahead, please have a look at the MessagesController@store which is the method responsible for inserting data into the database (obviously!)

Keep in mind that at this point, if I select a checkbox (user) and send him a message, 2 rows in the database get created.

public function store()
{
    $input = Input::all();
    $thread = Thread::create(
        [
            'subject' => $input['subject'],
        ]
    );
    // Message
    Message::create(
        [
            'thread_id' => $thread->id,
            'user_id'   => Auth::user()->id,
            'body'      => $input['message'],
        ]
    );
    // Sender
    Participant::create(
        [
            'thread_id' => $thread->id,
            'user_id'   => Auth::user()->id,
            'last_read' => new Carbon,
        ]
    );
    // Recipients
    if (Input::has('recipients')) {
        $thread->addParticipants($input['recipients']);
    }
    return redirect('messages');
}

So I started integrating Typeahead JS instead of the checkboxes.

First, I created the route

Route::get('messages/data/usernames/{query?}', 'MessagesController@getUsernames');

Then I created a function in MessagesController to get the usernames and return JSON

public function getUsernames($query = '') {
    $q = User::select('id', 'username');
    if ($query) {
        $q->where('username', 'LIKE', '%' . $query . '%');
    }
    return Response::json($q->get());
}

I then edited create.blade.php and added the input fields

<div class="form-group" id="remote">
   <input class="form-control typeahead" type="text" placeholder="Choose a Username" name="username_name">
   <input type="hidden" class="username_id" value="" name="username_id">
</div>

And this is the JS

var usernames = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('username'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    prefetch: 'data/usernames',
    remote: {
        url: 'data/usernames/%QUERY',
        wildcard: '%QUERY'
    }
});
$('#remote .typeahead').typeahead(null, {
    name: 'username',
    display: 'username',
    source: usernames
});
$('#remote .typeahead').bind('typeahead:select', function(ev, suggestion) {
    $('.username_id').val(suggestion.id);
});

So when I start typing a name, it auto-completes it and I can select it and carry on with the message. But no record in the database is being insert with the recipient's ID.

Only 1 record is being created with my user ID, there's no trace of the recipient's ID in the table, therefore, no messages are being delivered.

PS: I messaged the author of the package and he said he has no desire to change the checkboxes or even looking at my code.



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire