Link to home
Start Free TrialLog in
Avatar of Eduardo Fuerte
Eduardo FuerteFlag for Brazil

asked on

Could you point how to refresh data at a Laravel view when data to be presented changes ?

Hi Experts

Could you point how to refresh data at a Laravel view when data to be presented changes ?

When the page is initially presented it shows all the images.

Then a filter is applied and the collection to be presented is much smaller. The view is called the same way it was for all the images, but the images presented are not actualized.

If the view is started with the data filtered it's correctly presented.

Thanks in advance.
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Hey Eduardo,

You have a few choices here, depending on how you've implemented the Filter function.

You could just make another request to the server (effectively re-loading the page). You could make an AJAX call to the server and re-populate the page once you have a response (reduced list of images). You just just use some Javascript to hide the images that don't match the filter.

Will need more info before giving you any specific answers.
Avatar of Eduardo Fuerte

ASKER

Hi Chris


Still not considering what you posted about relationships at the precedent question.

Here is the data presented when the user opens the view (all the images)

 $vitrinesX = Vitrine
	::with('user_vitrine')
	->ativa()
	->aprovada()
	->global(Auth::user()->tipoparticipante_id)
	->orderBy('id','desc')
	->withCount([
		'user_vitrine as qtdeCurtiu' => function (Builder $query) { $query->where('curtiu', 1); },
	])
	->paginate(6);
	
return view('vitrines.index',compact('vitrinesX', 'vitrine','qtdeCurtiu','qtdeNaoCurtiu','curtiu'));

Open in new window


Then when the user applies the filter, the result of the filtered data showed by info is correct. If I use this right of the start the data presented is OK, indeed just one image.

        $vitrinesX = auth()->user()
            ->vitrines()
            ->with('user_vitrine')
            ->ativa()
            ->aprovada()
            ->global(Auth::user()->tipoparticipante_id)
            ->orderBy('id','desc')
            ->withCount([
                'user_vitrine as qtdeCurtiu' => function(Builder $query) { $query->where('curtiu', 1); },
            ])
            ->paginate(3);

return view('vitrines.index',compact('vitrinesX', 'vitrine','qtdeCurtiu','qtdeNaoCurtiu','curtiu'));

Open in new window


I guess the AJAX code must to run after the Filter button isn't it?

            <div class='col-md-4 pull-right'>
              <div class="btn-group" role="group">
                <button type="button" class="btn btn-primary" onclick="hotsite.vitrine.novo();">
                  <i class="fas fa-video" aria-hidden="true"></i> Todas as Fotos
                </button>
              </div>
            </div>

Open in new window




Vitrine.prototype.minhasfotos = function(){
  $.ajax({
    url: '/vitrine/minhasfotos',
    method: "GET",
    dataType: "html",
    error:function(data){
      hotsite.openModalCustom("Erro", "Erro ao carregar vitrine.", "Entendi", "error");
    },
    success: function(data){
      $('#midiaList').html(data);
    }
  });
}

Open in new window

I can't see a connection between your HTML and you Javascrip. Your HTML is firing a function called novo, but your javascript shows a funcrtion called minhasfotos. What's the connection between the 2.

If you're wanting to update the content after an AJAX call, then your server will need to responsd with only part of the final HTML - not a full page.
Sorry. I had copyed from the worng place. Here it is:

            <div class='col-md-4 pull-right'>
              <div class="btn-group" role="group">
                <button type="button" class="btn btn-primary" onclick="hotsite.vitrine.minhasfotos();">
                  <i class="fas fa-video" aria-hidden="true"></i> Minhas Fotos
                </button>
              </div>
            </div>

Open in new window



And the controller method that filters the data:

public function minhasFotos(Request $request){

        
        $curtiu = 0;


        $vitrinesX = auth()->user()
            ->vitrines()
            ->with('user_vitrine')
            ->ativa()
            ->aprovada()
            ->global(Auth::user()->tipoparticipante_id)
            ->orderBy('id','desc')
            ->withCount([
                'user_vitrine as qtdeCurtiu' => function(Builder $query) { $query->where('curtiu', 1); },
            ])
            ->paginate(3);
            
                    
        info($vitrinesX);       
        
        return view('vitrines.index',compact('vitrinesX', 'vitrine','qtdeCurtiu','qtdeNaoCurtiu','curtiu'));

    }

Open in new window



And the page part that must to be actualized:
<div class='row'>

    <input type="hidden" id="hdnCurtiu" value="{{$curtiu}}">
    
    <div class="col-md-12 col-sm-12">

            <section class="row">
           
                    @foreach($vitrinesX->chunk(3) as $row)
                    
                        @foreach($row as $vitrine)
      
                      
                           <div class="col-sm-12 col-md-4">
                           
                                @php 
                                
                                    $vitrine->liked_by= $vitrine->user_vitrine->pluck('id');
                                    
                                    $currentUserId = auth()->user()->id;
                                    $hasUserVoted = $vitrine->liked_by->contains($currentUserId); 
                                @endphp
                           
                                <div class="box-noticias">
                                   	<a href="javascript:void(0);" onclick='hotsite.vitrine.abrirVitrine({{$vitrine->id}});' >
                                    <img src="{{ $vitrine->url }}">
            	    			    </a>                    
                                </div> 
                                
                                <p id="like" class="likes" @if (!$hasUserVoted ) onclick="hotsite.vitrine.salvarEscolha({{ $vitrine->id }}, 1, this)" @endif>
                                    <i class="fa fa-thumbs-up"></i> <span id="qtdeCurtiu_{{ $vitrine->id }}">{{ $vitrine->qtdeCurtiu }}</span>
                                </p> 
      
                 
                           </div>     
                          
                        @endforeach
                        
                    @endforeach
                      
                                              
            </section>
            
           <div class='col-md-6 pull-right'>
                {{ $vitrinesX->links() }}
            </div> 
            
		</div>

</div>

Open in new window

OK. You will need to make sure that your controller method is only returning the part that you want to update - already rendered. Currently you've got this:

return view('vitrines.index', ...

You need to make sure that that view you return is only the necessary part of the page and that you call render() on it:

return view('partialtemplate',compact('vitrinesX', 'vitrine','qtdeCurtiu','qtdeNaoCurtiu','curtiu'))->render();

Open in new window

Hi Chris

In my case how to define the partialtemplate (I guess the last code I sent above)?

The data to be shown is correctly retrieved:

 User generated image
Hey Eduardo,

It just a standard blade template, the same as any other, but instead of being a full HTML page, it just contains the HTML that you need (i.e it's just returning a partial bit of HTML)
If I well understood...

I must to create under \views\layout\

(where the templates remains at my project)

Another layout with the loop part above at the code - and then extend it at the existent view, isn't it?
I mean

Copy this part of the view:

<div class='row'>

    <input type="hidden" id="hdnCurtiu" value="{{$curtiu}}">
    
    <div class="col-md-12 col-sm-12">

            <section class="row">
           
                    @foreach($vitrinesX->chunk(3) as $row)
                    
                        @foreach($row as $vitrine)
      
                      
                           <div class="col-sm-12 col-md-4">
                           
                                @php 
                                
                                    $vitrine->liked_by= $vitrine->user_vitrine->pluck('id');
                                    
                                    $currentUserId = auth()->user()->id;
                                    $hasUserVoted = $vitrine->liked_by->contains($currentUserId); 
                                @endphp
                           
                                <div class="box-noticias">
                                   	<a href="javascript:void(0);" onclick='hotsite.vitrine.abrirVitrine({{$vitrine->id}});' >
                                    <img src="{{ $vitrine->url }}">
            	    			    </a>                    
                                </div> 
                                
                                <p id="like" class="likes" @if (!$hasUserVoted ) onclick="hotsite.vitrine.salvarEscolha({{ $vitrine->id }}, 1, this)" @endif>
                                    <i class="fa fa-thumbs-up"></i> <span id="qtdeCurtiu_{{ $vitrine->id }}">{{ $vitrine->qtdeCurtiu }}</span>
                                </p> 
      
                 
                           </div>     
                          
                        @endforeach
                        
                    @endforeach
                      
                                              
            </section>
            
           <div class='col-md-6 pull-right'>
                {{ $vitrinesX->links() }}
            </div> 
            
		</div>

</div>

Open in new window


to a file   fotos.blade.php  (f.e.)


And then change this code at the actual view with:

@extends('layouts.fotos')

Ans then at the Controller

 return view('fotos',compact('vitrinesX', 'vitrine','qtdeCurtiu','qtdeNaoCurtiu','curtiu'))->render();

Open in new window


Is it correct?
Not quite.

You don't need to extend anything - you just need your AJAX request to return only a PART of your HTML view, so just return the fotos template.
Hard to me to follow what you means...


At Controller

return view('partialview',compact('vitrinesX', 'vitrine','qtdeCurtiu','qtdeNaoCurtiu','curtiu'))->render();

Open in new window


How to define this partialtemplate (where remains the HTML photos) at the code?


The AJAX code:

Vitrine.prototype.minhasfotos = function(){
  $.ajax({
    url: '/vitrine/minhasfotos',
    method: "GET",
    dataType: "html",
    error:function(data){
      hotsite.openModalCustom("Erro", "Erro ao carregar vitrine.", "Entendi", "error");
    },
    success: function(data){
      $('#midiaList').html(data);
    }
  });
}

Open in new window


I couldn't link the parts...
ASKER CERTIFIED SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi Chris


It makes all the sense.

It's just a matter of to use an @include.

I just created another view called:  fotos.blade.php  with the content of the foreach etc. above.

Then changes on the view:

  <div class='row'>
    <div id="midiaList">
      @include('vitrines.fotos')
    </div>
  </div>

Open in new window


And at the Controller:
return view('vitrines.fotos',compact('vitrinesX','curtiu'))->render();

Open in new window


And so... now it's running!
Excellent. So now when your page first runs it will include the vitrines.fotos template, and then when your AJAX call is made, it will reload just that template and replace the content on #midiaList.

Good stuff :)
Chris

Thank you for another very elucidative solution!

My Laravel's knowledge is growing thanks for your help...Sometimes I feel Laravel as "another PHP" inside PHP...
Haha - I know what you mean. It certainly has some quirks but when it makes sense, it's much easier to develop applications. It uses fairly modern design patterns to do the jon, and these design patterns are often very different from how many developers are used to writing code.

At it's core, it take an Object Oriented Programming (OOP) approach. If you understand how OOP development works, then using Laravel will make much more sense. OOP is not specific to any language - it's just a concept on how to program, so if you have some spare time, it might help to read up a little about the concepts behind OOP.

Good luck with it