Avatar of Eduardo Fuerte
Eduardo Fuerte
Flag 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.
LaravelPHP

Avatar of undefined
Last Comment
Chris Stanyon

8/22/2022 - Mon
Chris Stanyon

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.
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

Chris Stanyon

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.
Your help has saved me hundreds of hours of internet surfing.
fblack61
Eduardo Fuerte

ASKER
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

Chris Stanyon

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

Eduardo Fuerte

ASKER
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:

 img002
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Chris Stanyon

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)
Eduardo Fuerte

ASKER
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?
Eduardo Fuerte

ASKER
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?
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
Chris Stanyon

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.
Eduardo Fuerte

ASKER
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
Chris Stanyon

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Eduardo Fuerte

ASKER
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!
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Chris Stanyon

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 :)
Eduardo Fuerte

ASKER
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...
Chris Stanyon

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
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes