Croping multible images with laravel 5

Of course first of all we need to add some routes in which we call a page with a get request and store the data with a post request. it’ll look somethign like this:

Route::get('/uploads', 'UploadController@index');
Route::post('/uploads', 'UploadController@store');

After this we need that Controller, I called it UploadController, as you know there are 2 ways how to add a new controller and I chose the Terminal one, by pressing the command

php artisan make:Controller UploadController

Or as I like to do it 

php artisan make:model Upload -r

Which makes a model and a resourceful controller for the model. 

with a first method you allso need to add a model but also pressing the command

php artisan make:model Upload

in the controller for the index methode as we saw on the get request route we just need to write it like this

public function index(){
   return view('uploads');
}

so we get the desired view. 

let’s just continue with the view for the upload images. first you need to get a +2 Jquery version and add it tot the head of your project, something like this:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

and also add the cropit js which you can find here move to, Cropit > dist > jquery.cropit.js then just call it like this:

<script src="js/cropit.js"></script>

the css

      .cropit-preview {
        background-color: #f8f8f8;
        background-size: cover;
        border: 1px solid #ccc;
        border-radius: 3px;
        margin-top: 7px;
        width: 250px;
        height: 250px;
      }

      .cropit-preview-image-container {
        cursor: move;
      }

      .image-size-label {
        margin-top: 10px;
      }

      input {
        display: block;
      }

      button[type="submit"] {
        margin-top: 10px;
      }

      #result {
        margin-top: 10px;
        width: 900px;
      }

      #result-data {
        display: block;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        word-wrap: break-word;
      }
    

the html

 <form action="uploads" method="post" enctype="multipart/form-data">
      {{ csrf_field() }}
      
        <div class="image-editor">
          <input type="file" class="cropit-image-input">
          <div class="cropit-preview"></div>
          <div class="image-size-label">Resize image</div>
          <input type="range" class="cropit-image-zoom-input">
          <input type="hidden" name="data" class="hidden-image-data" />
        </div>

        <div class="image-editor2">
          <input type="file" class="cropit-image-input">
          <div class="cropit-preview"></div>
          <div class="image-size-label">Resize image</div>
          <input type="range" class="cropit-image-zoom-input">
          <input type="hidden" name="data2" class="hidden-image-data2" />
        </div>
        <button type="submit" id="sub">Submit</button>
</form>

of course you can modify the html as you wish as long as you add all the right componens with ti. also don’t forget the javascript wich is an important part of all this

    <script>

      $(function() {
        $('.image-editor').cropit();
        $('.image-editor2').cropit();

        $('form').submit(function() {
          // Move cropped image data to hidden input
          let imageData = $('.image-editor').cropit('export');
          let imageData2 = $('.image-editor2').cropit('export');
          $('.hidden-image-data').val(imageData);
          $('.hidden-image-data2').val(imageData2);

          // Print HTTP request params
          let formValue = $(this).serialize();
          $('#result-data').text(formValue);

          // Prevent the form from actually submitting
          return true;
        });
      });
    </script>

here is the refactored version of this if you don’t like to write too much code.

//crop functionality
$(function() {
for(let i = 1; i <= 12; i++) {
$('.image-editor' + i).cropit();
}
// $('.image-editor' + photoTypeId).cropit();
$('form').submit(function() {
// Move cropped image data to hidden input
for(let p = 1; p <= 12; p++) {
let imageData = $('.image-editor' + p).cropit('export');
$('.hidden-image-data' + p).val(imageData);
}
// Print HTTP request params
letformValue = $(this).serialize();
$('#result-data').text(formValue);
// Prevent the form from actually submitting
return true;
});
});

after you’ve added everything as you want, you can open the page wich should look like this

Lets continue with the second part of the adventure, the store medoth on the controller

public function store(Request $request)
    {
       $imageData = $request->file('data');
       $imageData2 = $request->get('data2');

       $info = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $imageData));
       $info2 = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $imageData2));

       Image::make($info)->save(public_path('/images/1.png'));
       Image::make($info2)->save(public_path('/images/2.png'));

       return redirect()->back();
    }

You’re still not done, you need to add a package in order to make this work, thankfully you can do this with laravel and a simple command.

as you can see we used a phasade called Image we’ve dont this by importing intervention.io folow the instructions there and add it to your project font forget the add it to the beggining of the project like so:

use Intervention\Image\ImageManagerStatic as Image;

after you’ve added this and the data is right you now can crop and store the croped images on the server.

have fun.

Add multible wysiwig editors to use in one page

In this tutorial we will see how to add multible wysiwig editors, converting textareas to wysiwig editors. 

Dependecies: For this we will use CKeditor

CKEditor is a WYSIWYG rich text editor which enables writing content directly inside of web pages or online applications. Its core code is written in JavaScript and it is developed by CKSource. CKEditor is available under open source and commercial licenses more here

First things first, we will need to import ckeditor so we are able to use it depending on what you are using you can call is as you want like so for example:

<script type="text/javascript" src="{{ asset('plugins/ckeditor-basic/ckeditor.js') }}"></script>

or use the CDN the currect version is 4.10.1

<script src="https://cdn.ckeditor.com/4.10.1/standard/ckeditor.js"></script>

add the textarea like so:

<textarea name="shortProfilePartnerOrganisation" class="form-control ckeditor" rows="5" id="shortProfilePartnerOrganisation"></textarea>

Than the js that makes it posible to add multible ckeditors like so

<script> 
// To make a text area with wysiwyg editor add a class to that textarea with name ckeditor
function transgormToWYSIWYG() {
var ckeditors = $('.ckeditor');
$.each(ckeditors, function (index, ckeditor) {
CKEDITOR.replace(ckeditor, {
wordcount: {
// Whether or not you want to show the Word Count
showWordCount: true,

// Whether or not you want to show the Char Count
showCharCount: true,

// Maximum allowed Word Count
// maxWordCount: 4,
// Maximum allowed Char Count
maxCharCount: 1000
}
});
});
}
</script>

Afterwards just use it we you need it with the js function we made right above.

transgormToWYSIWYG();

Get a database value of another table in laravel

In laravel database relationships are simple, and to get a value of another table to another view based on the values you got in this view you simple connect these two tables with a relationship. 

Lets get a real world problem about this, For this I’ll get a website I’ve done before. 

lets say I’ve submitted a form and in this form I got a result. like in the image below.

Now based on this “ISFJ” result, I want to get a short description of this type from another table, where the descriptions are stored.

So what I’ve to do is to link them together So a the results belongs to a short description right?

to the Test class add this relationship code

public function tipi()
{
return $this->belongsTo(Tipi::class, 'finaltype', 'type');
}

so what we are doing there is connect the finaltype column which stores the ISFJ type, to the “type” table of the type description.

on the view, just add this code.

{!! $results->tipi->shortDescription !!}

So the $results variable is what you already use to connect to your table of this view, but you simply say use the connection mentioned above, in this case the function is public function tipi() so you used tipi as $results->tipi and at last what you want to get, in our case we need the short description.

and here you have it, based on the final type you get the short description

One view set multible service types in Laravel

If you have a request to use the same functionality, same view, same fields, but different types of for example a type of service, you can use in laravel you are able to use just one view and add multiple services with it, as long as the fields and views are the same.

Lets do an example with it.

Let’s start with the View to see what we are actually doing and how this might look like:

This view shows the index, which contains a table and a button to add the session. I’ll show more views for the other CRUD below afterwards.

Notice: I also added a button, in the code which is not shown in the preview above.

@extends('layouts.app')
@section('content')
<div class="container">
   <h1>Group Session</h1>
<div class="row" id="service-info">
  <div class="col-lg-12">
     <h3>Add new Session:</h3>
     <div class="col-md-4">
        <a href="{{  action('GroupSessionController@create', $serviceType) 
}}" class="btn btn-block cleftButton-c service-add"> {{ $serviceType- 
>ServiceDesc }} </a>
      </div>
   </div>
</div>
<div class="row">
   <div class="col-md-12">
     <h3>All Group Sessions</h3>
     <table class="table table-hover" id="myTable">
        <thead>
           <th>id</th>
           <th>Host</th>
           <th>Session Data</th>
           <th>Behavior</th>
           <th>Type</th>
           <th>Edit</th>
           <th>Delete</th>
        </thead>
        <tbody>
@foreach ($sessions as $session)
           <tr>
              <td>{{ $session->id }}</td>
              <td><a href="{{ action('GroupSessionController@show', [$serviceType, $session->id]) }}">{{ $session->host}}</a></td>
              <td>{{ $session->date}}</td>
              <td>{{ $session->behavior}}</td>
              <td>{{ $session->type}}</td>
              <td>
                 <a href="{{ action('GroupSessionController@edit', [$serviceType, $session->id]) }}" class="btn btn-primary btn-xs">
                 <i class="fa fa-pencil" aria-hidden="true"></i> Edit
                 </a>
              </td>
              <td data-title="@lang('patient.delete')">
                 <form action="{!! action('GroupSessionController@destroy', [$serviceType, $session->id]) !!}" method="POST">
                    {{csrf_field()}}
                    {{ method_field('DELETE') }}
                    <a class="label label-danger" class="btn btn-danger btn-xs"><i class="fa fa fa-trash-o "></i>Delete</a>
                 </form>
              </td>
           </tr>
@endforeach
        </tbody>
     </table>
    </div>
  </div>
</div>
{{--ontainer--}}
@endsection

Next I wanna show, the migration so we know will what data we are dealing with.

For this I just need 2 tables one for the Service Type (ServiceType) and the other for the data to be added in the forms we provided in the create and edit views.

Add this to the migration file for the up method.

class CreateGroupSessionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('group_sessions', function (Blueprint $table) {
            $table->increments('id');
            $table->string('photo');
            $table->string('host');
            $table->dateTime('date');
            $table->string('behavior');
            $table->string('type');
            $table->unsignedSmallInteger('ServiceTypeId');
            $table->timestamps();
        });
    }
/* ... */

You also need a table where you store the different types for a table:

class CreateServicetypeTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('ServiceType', function (Blueprint $table) {
            $table->smallInteger('ServiceTypeId')->primary();
            $table->char('ServiceCode', 3);
            $table->string('ServiceDesc', 50);
            $table->boolean('Order');
        });
    }

Of course you need to do a model for the session groups

in the model of I named it GroupSession.php you can add a method to make a relationship of many to one, like this:

public function servicetype()
{
    return $this->belongsTo(ServiceType::class);
}

allso for the service type model which I named ServiceType.php you need to add a has many method

public function groupSessions()
{
    return $this->hasMany('App\GroupSession', 'ServiceTypeId', 'ServiceTypeId');
}

Before we come to the interesting part we need to add some routes. Which we can do in two ways, a resourceful router or we add routers individually.

in the example below I showed the resourceful router first and the other routers individually commented, so if you want to use them all you need to comment and adapted them for your project of course.

Route::resource('{serviceType}/groupSession', 'GroupSessionController');

//Route::get('/groupsession/{serviceType}', 'GroupSessionController@index');
//Route::get('/groupsession/{serviceType}/create', 'GroupSessionController@create');
//Route::get('/groupsession/{serviceType}/{groupSession}', 'GroupSessionController@show');
//Route::get('/groupsession/{serviceType}/{groupSession}/edit', 'GroupSessionController@edit');
//Route::put('/groupsession/{serviceType}/{groupSession}', 'GroupSessionController@update');
//Route::post('/groupsession/{serviceType}', 'GroupSessionController@store');
//Route::delete('/groupsession/{serviceType}/{groupSession}', 'GroupSessionController@destroy');

Now comes the interesting part, the Controller which defines the CRUD logic for this solution

Lets start with the index that we saw above, in the view example.

This function simple takes, the serviceType parameter and  uses it in a simple query in it. in this case also according to the route it adds the service type id to the URL.

public function index(ServiceType $serviceType)
{
    $sessions = GroupSession::where('ServiceTypeId' , $serviceType->ServiceTypeId)->get();

    return view('groupSession.index', compact('sessions', 'serviceType'));
}

The Create, looks looks this.

also very simple right?,  it also takes in the ServiceType and simply returns the create view and gives the serviceType along.

public function create(ServiceType $serviceType)
{
    return view('groupSession.create', compact('serviceType'));
}

The view could look this this.

you can add a h1 header to show the service type name in this case I named it ServiceDesc like this

<h1 style="margin-top: 110px;">Create {{ $serviceType->ServiceDesc }} - Group Session</h1>

then simple add the form as it is

<form id="create-form" action="{!! action('GroupSessionController@store', $serviceType) !!}" method="POST" enctype="multipart/form-data">
    {{ csrf_field() }}
        <section class="row">
            <div class="col-md-5">
                <div class="form-group">
                    Group photo
                    <br>
                    <input class="add-img" type="file" name="file" accept="image/x-png,image/gif,image/jpeg" required>
                    <br>
                </div>
            </div>
            <div class="col-md-7">
                <div class="form-group">
                     Host
                    <input name="host" type="text" class="form-control" id="host" required/>
                </div>
                <div class="form-group">
                    Session Date 
                    <input name="date" type="text" class="form-control datepicker-field" id="sessiondate" required/>
                </div>
                <div class="form-group">
                    Behavior
                    <select class="form-control" name="behavior" title="" required>
                        <option value=""></option>
                        <option value="option1">option1</option>
                        <option value="option2">option2</option>
                    </select>
                </div>
                <div class="form-group">
                    Type
                    <select class="form-control" name="type" title="" required>
                        <option value=""></option>
                        <option value="option1">option1</option>
                        <option value="option2">option2</option>
                        <option value="option3">option3</option>
                        <option value="option4">option4</option>
                    </select>
                </div>
            </div>
        </section>
        
        <section class="add-people row">
            <h4>Add Session Attendees</h4>
            <div class="people-container">
                <button class="add-new btn btn-success" type="button"><i class="fa fa-plus"></i> Add new Attendee</button>
            </div>
        </section>
    <hr>
    <input class="btn btn-success pull-right" type="submit"  />
</form>

To store this use a controller like this.

What I’ve done here is simply get the GroupSessionRequest and the ServiceType as a parameter. and returned a variable with the right query. also for the attendees as I have added this to the form above. you simple can use just the group session without the attendees.

public function store(GroupSessionRequest $request, ServiceType $serviceType)
{
    $groupSession = $serviceType->groupSessions()->create($request->all());

    $groupSession->sessionAttendee()->createMany($request->input('sessionAttende'));

    return redirect()->action('GroupSessionController@index', $serviceType);
}

Let’s continue with the edit

it’s almost the same as the create as always you just need to get the right id as well. so for a header you can also use it like this.

<h1>Edit {{ $serviceType->ServiceDesc }} - Group Session  - {{ $session->id }}</h1>

the form could look something like this.

<form action="{!! action('GroupSessionController@update', [$serviceType, $session->id]) !!}" method="POST" enctype="multipart/form-data">
    {{ csrf_field() }}
    {{ method_field('put') }}

    <section class="main-data row">
        <div class="col-md-5">
            <div class="form-group">
                Group photo:
                <br>
                <input type="file" name="file" accept="image/x-png,image/gif,image/jpeg">
                <br>
            </div>
        </div>
        <div class="col-md-7">
            <div >
                <div class="form-group">
                    Host:
                    <input name="host" type="text" class="form-control" id="host" value="{{ $session->host }}" />
                </div>
            </div>
            <div >
                <div class="form-group">
                    Session Date:
                    <input name="date" type="text" class="form-control datepicker-field" id="sessiondate" value="{{ $session->date }}" />
                </div>
            </div>
            <div >
                <div class="form-group">
                    Behavior:
                    <select class="form-control" name="behavior" title="" required>
                        <option value=""></option>
                        <option value="option" {{ $session->behavior === "option" ? 'selected' : '' }}>option</option>
                        <option value="option"{{ $session->behavior === "option" ? 'selected' : '' }}>option</option>
                    </select>
                </div>
            </div>
            <div >
                <div class="form-group">
                    Type:
                    <select class="form-control" name="type" title="" required>
                        <option value=""></option>
                        <option value="option" {{ $session->type === "option" ? 'selected' : '' }}>option</option>
                        <option value="option" {{ $session->type === "option" ? 'selected' : '' }}>option</option>
                        <option value="option" {{ $session->type === "option" ? 'selected' : '' }}>option</option>
                        <option value="option" {{ $session->type === "option" ? 'selected' : '' }}>option</option>
                    </select>
                </div>
            </div>
        </div>
    </section>

and the controller, like this.

public function edit(ServiceType $serviceType, GroupSession $groupSession){

    return view('groupSession.edit', ['session'=> $groupSession, 'serviceType' => $serviceType]);
}

also for the update method

public function update(GroupSessionRequest $request, ServiceType $serviceType, GroupSession $groupSession)
{
    // $groupSession = GroupSession::update($request->all());
    $groupSession->update($request->all());
    
    if($request->hasFile('file')){
        $media = MediaUploader::fromSource($request->file('file'))
            ->toDestination('local', "media/group_session")
            ->upload();
            
        $groupSession->attachMedia($media, 'groupsession');
    }

    foreach(request()->input('sessionAttende') as $id => $value){
        $sessionAttendee = SessionAttendee::find($id);
        
        if($sessionAttendee){
            $sessionAttendee->update($value);
        }else{
            $groupSession->sessionAttendee()->create($value);
        }
    }

at last the delete,

public function destroy(ServiceType $serviceType, GroupSession $groupSession){
$groupSession->delete(); FlashAlert::build('success', 'Session deleted successfully.'); return back(); 
}

Create multiple form groups with multiple fields in Laravel and jQuery

If I have for example a group session or a course class, and I want to add all attendees, I need to provide a solution to add all my attendees without knowing how many will be there, It could be 1 or 10 you’ll never know.

So we just append some fields, as we want with jQuery, and and add them to a specific table on the database.

Like this could be the final product then.

Let’s start with the frontend.

The Frontend

Using Boostrap, I’ll made a form with some different fields for the group session, and also included a group Session photo. For the non repeatable fields I chose: the session photo, Host, Session Date, Type, And for the repeatable fields, just a button for now, because we will add the fields with jQuery.

[alert style=”warning”]Keep in mind that, all uppercase words indicate that you need to adjust it with your project. Except the form method[/alert]

<form id="THEFORM" action="{!! action('THECONTROLLER@store') !!}" method="POST" enctype="multipart/form-data">
    {{ csrf_field() }}

    <div class="row">
        <section class="main-data row">
            <div class="col-md-5 fillerr">
                <div class="form-group">
                    Group photo

                    <br>
                    <input class="add-img" type="file" name="file" onchange="readURL(this);" accept="image/x-png,image/gif,image/jpeg">
                    <br>
                </div>
            </div>
            <div class="col-md-7">
                <div class="form-group">
                     Host
                    <input name="host" type="text" class="form-control" id="host" />
                </div>
                <div class="form-group">
                    Session Date 
                    <input name="date" type="text" class="form-control id="sessiondate" />
                </div>
                <div class="form-group">
                    Type
                    <select class="form-control" name="type" title="" required>
                        <option value=""></option>
                        <option value="FIRST">FIRST</option>
                        <option value="SECOND">SECOND</option>
                        <option value="THIRD">THIRD</option>
                        <option value="FOURTH">FOURTH</option>
                    </select>
                </div>
            </div>
        </section>
        
        <section class="add-people row">
            <h4>Add Session Attendees</h4>
            <div class="people-container">
                <button class="add-new btn btn-success" type="button"><i class="fa fa-plus"></i>Add new Attendee</button>
            </div>
        </section>
    </div>

    <hr>
    <input class="btn btn-success pull-right" type="submit"  />
</form>

The Javascript

The js, adds some fields, to the add-people section, so for this I just needed 3 simple fields, the name, surname, and birthday, of course you can add more.

Simply enough we wait for the document to load, add some Variables, such as how much fields, is the maximum, indication the wrapper, and which button are we using to add the fields, in this case it’s wrapper, as people-container, and the button is add-new, all referring to classes. I also added a x variable with the default value 0, so I know how many fields, are there this can be used for validation as well. the I targeted the button and added a click event to it. by preventing the default I don’t allow the button to submit the form. and looked up if there are any fields, with the if function. added one to the x variable, and appended the complete html to the wrapper. because I had a data field there and I wanted to use the jQuery date picker I left a date-picker Method in there for every fields that is creased. as well in there. at last on the else class I added a simple alert to tell that the limit is reached.  and provided the code to remove a field.

$(document).ready(function() {
    var max_fields      = 50;
    var wrapper         = $(".people-container");
    var add_button      = $(".add-new");
    var x = 0;

    $(add_button).click(function(e){
        e.preventDefault();
        if(x < max_fields){
            x++;
            $(wrapper).append(
                '<div class="filedset attendee">' +
                    '<div class="col-md-3 col-md-offset-1">' +
                        '<div class="form-group">Name<input type="text" class="form-control" name="sessionAttende[' + x + '][name]" title="" autocomplete="given-name" ></div>' +
                    '</div>' +
                    '<div class="col-md-3">' +
                        '<div class="form-group">Surname<input type="text" class="form-control" name="sessionAttende[' + x + '][surname]" title="" autocomplete="given-name" ></div>' +
                    '</div>' +
                    '<div class="col-md-3">' +
                        '<div class="form-group">Birthday<input name="sessionAttende[' + x + '][birthday]" type="text" class="form-control datepicker-field" id="dateField' + x + '" /></div>' +
                    '</div>' +
                    '<br><button class="delete btn btn-danger" type="button"><i class="fa fa-minus"></i></button>' +
                '</div>'); //add input box

             $(".datepicker-field").datepicker({
                changeYear: true,
                dateFormat: "dd-mm-yy",
                yearRange: "-100:+0",
                maxDate : "0",
            });
        }
else
{
alert('You Reached the limits')
}
    });
    $(wrapper).on("click",".delete", function(e){
        e.preventDefault(); $(this).parent('div').remove(); x--;
    })
});

The Controller

Now comes the interesting part.  so because for this I use Laravel 5.6 I am able to use some cool stuff, for now.

So I just request all fields with the $request->all() method, to the create() methode, and used the GroupSession facade for the model.  for the file aka the Session Image, I used the MediaUploader but you can use normal Laravel for this as well, of course.

and for the repeatable fields, added the createMany() methode to the SessionAttendee model, and requested all sessionAttende fields.

at last redirected to a view, and good is.

use IlluminateHttpRequest;
use AppGroupSession;
use MediaUploader;
use AppSessionAttendee;

public function store(Request $request)
{
    $groupSession = GroupSession::create($request->all());

    if($request->hasFile('file')){
        $media = MediaUploader::fromSource($request->file('file'))
            ->toDestination('local', "media/group_session")
            ->upload();
            
        $groupSession->attachMedia($media, 'groupsession');
    }

    $groupSession->sessionAttendee()->createMany($request->input('sessionAttende'));

    return redirect('groupsession');
}

The Models

For this I needed 2 models, and used a many-to-one relationship for the non-repeatable and repeatable fields.

The GroupSession

In this Model I added a protected fillable, for the non-repeatable fields, and build the relationship with SessionAttendee model,

use IlluminateDatabaseEloquentModel;
use PlankMediableMediable;
use CarbonCarbon;
use SpatieActivitylogTraitsLogsActivity;

class GroupSession extends Model
{
    use Mediable, LogsActivity;
    
    protected $fillable = [
        'host',
        'date',
        'behavior',
        'type',
    ];

    // one to many with session attendees
    public function sessionAttendee()
    {
        return $this->hasMany(SessionAttendee::class);
    }
}

The SessionAttendee Model

In this Model, I needed to use the belongsTo() method to connect it with GroupSession

use IlluminateDatabaseEloquentModel;
use CarbonCarbon;
use SpatieActivitylogTraitsLogsActivity;

class SessionAttendee extends Model
{
    use LogsActivity;

    protected $table = 'session_attendiees';

    protected $fillable = ['name', 'surname', 'birthday'];

    public function groupSession()
    {
        return $this->belongsTo(GroupSession::class);
    }

    public function setBirthdayAttribute($value)
    {
        $this->attributes['birthday'] = new Carbon($value);
    }
}

The Migrations

The Session Table, Migration contains these fields,

public function up()
{
    Schema::create('group_sessions', function (Blueprint $table) {
        $table->increments('id');
        $table->string('photo');
        $table->string('host');
        $table->dateTime('date');
        $table->string('behavior');
        $table->string('type');
        $table->timestamps();

    });
}

and the other one:

Schema::create('session_attendiees', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('group_session_id');
    $table->string('name');
    $table->string('surname');
    $table->date('birthday');
    $table->timestamps();

});

So as you can see the first one is the non-repeatable and the second one repeatable. and it's the same as the fields.

Tech Versions.

  • Laravel 5.6
  • Jquery 2.x

Laravel cool helpers, Optional()

optional()
The optional function accepts any argument and allows you to access properties or call methods on that object. If the given object is null, properties and methods will return null instead of causing an error:

return optional($user->address)->street;

{!! old('name', optional($user)->name) !!}
The optional function also accepts a Closure as its second argument. The Closure will be invoked if the value provided as the first argument is not null:

return optional(User::find($id), function ($user) {
return new DummyUser;
});

Redirect to a specific tab after deleting or inserting in laravel

Gaving multible tabs in a view in Laravel with a full functional CRUD, could do some problems as you try to navigate back to the specific tab where you were before, after inserting, updating, or deleting an item. With Laravel you usually return a view (return view(args);) or redirect back (return back(); ) in the end of the CRUD method.

I have discovered 2 ways to do this:

  1. Using Ajax
  2. Using Jquery and the withInput() method in the Controller

Let’s start with using Ajax

Inserting the information and returning to the same tab

The Ajax code below uses the form data with a POST method, and if the data is inserted successfully, return to the view with the parameter specific parameter given. reload the page (you might not need this part), else return an error message.

Keep in mind that you have to do this AJAX request for every tab or CRUD you have in this view. 

$('#addVideoForm').submit(function (form) {
varformData = newFormData(this);
$.ajax({
  method:'POST',
  url:"{{ action('Controller@store', [$var]) }}",
  data:formData,
  cache:false,
  contentType:false,
  processData:false,
  success:function (data) {
    varurl = '{!! action('Controller@index', [$var]) !!}';
    varfullUrl = url.concat('?#videos');
    window.location.href = fullUrl;
    location.reload();
    error:function (data) {
      if (data.responseJSON.video) {
        $('#video-error').attr('class', 'has-error').append(' <span class="help-block"><strong>' + data.responseJSON.video + '</strong></span>');
      }
      $('#upload').attr("disabled", false);
    }
  });
});

Basically  this is all you have to do. the page will return to the same tab, you have inserted the information.

Using Laravel controllers, for delete.

Deleting the information and returning to the same tab.

This method requires less code, and uses the back(); method in combo with the withInput(); method.

In this case i have 3 tabs, A video, a photo and a comments tab, using the destroy method from the associated controller, After using the data liks detaching the media and some

publicfunctiondestroy(param $param, Media $medium){
  $medium->delete();
  Session::flash('status', 'The video was successfully deleted.');
  //return to a specific tab, regarding the type the user added
  if ($medium->aggregate_type == Media::TYPE_VIDEO) {
    returnback()->withInput(['tab'=>'videos']);
  }
  elseif ($medium->aggregate_type == Media::TYPE_IMAGE) {
    returnback()->withInput(['tab'=>'photos']);
  }else{
    returnback();
  }
}
The js on the frontend
//redirect to specific tab
$(document).ready(function () {
  $('#myTab a[href="#{{ old('tab') }}"]').tab('show')
});
The HTML

My tab navigation:

<li><a href="#photos" data-toggle="tab"><i class="fa fa-camera" aria-hidden="true"></i> Photos</a></li>

My tab pane:

<div class="tab-pane" id="photos">
<ul class="nav nav-stacked nav-pills" id="myTab">

Show gif img only if form is validated

So the problem is I want to show a gif image to indicate that the form I’ve submited is being loaded, but even if the form is not validated the gif pops up, so what should I do?

to solwe this problem there is a simple jquery code you can use, by telling the page the show the gif only if the form is submited. Here’s what you need.

First of all thes look at the html:

<br />
<button class="btn btn-primary cleftButton pull-right" name="submit" type="submit"><br />
<i class="fa fa-save"></i><img id="loading" style="display: none;" src="img/loading.gif" alt="loading" width="15px" />   Save Data &amp; Photos<br />
</button><br />

So this html is a simple button with the type submit and it has am icon from fontAwesome and also a gif image which i’ve uploadad on the server, and refered the src at the right place. I also made sure the gif image is not too big and the display is set to non so it’s being hidden for the time being, also don’t forget the id because that’s where will refered to the js.

The js:

$(document).ready(function() {
  $("form").submit(function() {
    $('button[type=submit]').click(function () {
      $('#loading').removeAttr("style");
      $(".fa-save").hide();
      });
  });
});

So we start with the document ready functions to the script can do it’s thing for sure. Then we make sure the form is being submited by using the submit function, of course this is just for frontend validation but I don’t think that the gif will show up with the backend validation fails. The next step is the click function by waiting till the button with the submit type is clicked using the click function. And at last, removing the style attribut from the loading image by triggering the id of the image, and hide the save icon from fontawesome.

That’s all, easy right.

Multible upload progress bars

This tutorial shows how to make multiple uploading progress bars, inspired by Pretty Printed video, on how to make the progress bar. In my case I needed it to be multible for more then one input file types. So I came up with a solution. I don’t know if this is the best solution but it works. get it and make it better for yourself.

(I recommend to watch the video first and then see what has changed to my js code)

or use https://github.com/blueimp/jQuery-File-Upload/wiki/Setup

Here we have 3 input types and a submit button:

[code]

0%

0%


0%

[/code]

Then we have the Javascript file:

[code]

$(document).ready(function() {

var inputArr = [];

$(‘.file-input’).each(function (){
console.log(‘each’);
$(this).change(function() {

inputArr.push($(this).attr(‘id’));
console.log(inputArr);
$(this)
});
});
console.log(inputArr);
$(‘form’).on(‘submit’, function(event) {
event.preventDefault();
var formData = new FormData($(‘form’)[0]);
$.ajax({
xhr : function() {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener(‘progress’, function(e) {
if (e.lengthComputable) {
console.log(‘Bytes Loaded: ‘ + e.loaded);
console.log(‘Total Size: ‘ + e.total);
console.log(‘Percentage Uploaded: ‘ + (e.loaded / e.total))

var percent = Math.round((e.loaded / e.total) * 100);
// var files = $(“#document1”).val();
$.each(inputArr, function (index, value){
$(‘#’+value+’-progressbar’).attr(‘aria-valuenow’, percent).css(‘width’, percent + ‘%’).text(percent + ‘%’);
});
}
});

return xhr;
},
type : ‘POST’,
url : ‘/upload’,
data : formData,
processData : false,
contentType : false,
success : function() {
alert(‘File uploaded!’);
}
});

});

});

[/code]

the js works in that way that, at the begging you have an each loop which gets the inputs from a class then provices the progress bars with the right id so in this case the progress bar has an id of the value wich in this cas is “document1, 2, and 3″and added to it “-progressbar”