AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-4512005

Razvan Zamfir's questions

Martin Hope
Razvan Zamfir
Asked: 2025-04-23 20:54:00 +0800 CST

O plugin de truncamento funciona apenas na primeira página de uma tabela de tabelas de dados

  • 5

Estou usando DataTables para exibir, paginar e classificar um conjunto de dados.

new DataTable('#employees', {
  info: false,
  paging: true,
  filter: false,
  "aLengthMenu": [5, 10],
  initComplete: function() {
    if (this.api().page.info().pages < 2) {
      $('.dt-paging').hide();
    }
  }
});

$(document).ready(function() {
  $('.truncate').block_ellipsis({
    lines: 2,
    more: function(nb) {
      return '<span class="badge bg-secondary">Show ' + nb + ' more</span>';
    },
    less: '<span class="badge bg-secondary">Show less</span>'
  });
});
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/2.1.8/css/dataTables.bootstrap5.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js"></script>
<script src="https://cdn.datatables.net/2.1.8/js/dataTables.min.js"></script>
<script src="https://cdn.datatables.net/2.1.8/js/dataTables.bootstrap5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://www.jqueryscript.net/demo/jQuery-Plugin-To-Show-ide-Block-Elements-Block-Ellipsis/dist/block_ellipsis.js"></script>



<div class="container-fluid my-2">
  <h2>Data Tables</h2>
  <table id="employees" class="table table-bordered table-striped mx-1">
    <thead>
        <tr>
            <th class="w-auto">Name</th>
            <th class="w-25">Position</th>
            <th class="w-10">Office</th>
            <th class="w-25">Age</th>
            <th class="w-10">Skills</th>
            <th class="w-10">Salary</th>
        </tr>
    </thead>
    <tbody>
        <tr>            
            <td>Tiger Nixon</td>
            <td>System Architect</td>
            <td>Edinburgh</td>
            <td>61</td>
            <td class="truncate">
                <span class="badge rounded-pill bg-secondary">JavaScript</span>
                <span class="badge rounded-pill bg-secondary">CSS</span>
                <span class="badge rounded-pill bg-secondary">PHP</span>
                <span class="badge rounded-pill bg-secondary">Laravel</span>
                <span class="badge rounded-pill bg-secondary">Java</span>
                <span class="badge rounded-pill bg-secondary">Node</span>
                <span class="badge rounded-pill bg-secondary">CI/CD</span>
            </td>
            <td>$320,800</td>
        </tr>
        <tr>            
            <td>Garrett Winters</td>
            <td>Accountant</td>
            <td>Tokyo</td>
            <td>63</td>
            <td class="truncate">
                <span class="badge rounded-pill bg-secondary">JavaScript</span>
                <span class="badge rounded-pill bg-secondary">CSS</span>
                <span class="badge rounded-pill bg-secondary">PHP</span>
            </td>
            <td>$170,750</td>
        </tr>
        <tr>                
            <td>Ashton Cox</td>
            <td>Senior Software Developer</td>
            <td>San Francisco</td>
            <td>66</td>
            <td class="truncate">
                <span class="badge rounded-pill bg-secondary">JavaScript</span>
                <span class="badge rounded-pill bg-secondary">CSS</span>
                <span class="badge rounded-pill bg-secondary">PHP</span>
                <span class="badge rounded-pill bg-secondary">Laravel</span>
                <span class="badge rounded-pill bg-secondary">React</span>
                <span class="badge rounded-pill bg-secondary">Angular</span>
                <span class="badge rounded-pill bg-secondary">Java</span>
            </td>
            <td>$86,000</td>
        </tr>
        <tr>            
            <td>Cedric Kelly</td>
            <td>Senior Javascript Developer</td>
            <td>Edinburgh</td>
            <td>22</td>
            <td class="truncate">
                <span class="badge rounded-pill bg-secondary">JavaScript</span>
                <span class="badge rounded-pill bg-secondary">CSS</span>
            </td>
            <td>$433,060</td>
        </tr>
        <tr>            
            <td>Ștefan Popa</td>
            <td>Accountant</td>
            <td>Tokyo</td>
            <td>33</td>
            <td class="truncate">
                <span class="badge rounded-pill bg-secondary">CSS</span>
                <span class="badge rounded-pill bg-secondary">React</span>
            </td>
            <td>$162,700</td>
        </tr>
        <tr>            
            <td>Allan Smith</td>
            <td>Accountant</td>
            <td>London</td>
            <td>33</td>
            <td class="truncate">
                <span class="badge rounded-pill bg-secondary">CSS</span>
                <span class="badge rounded-pill bg-secondary">React</span>
            </td>
            <td>$162,700</td>
        </tr>
    </tbody>
  </table>
</div>

Estou usando o plugin Block Ellipsis para truncar as células na coluna "Habilidades" se elas forem muito longas.

O problema que enfrento é que o truncamento só funciona na primeira página de resultados.

O que causa esse problema e como posso corrigi-lo?

javascript
  • 1 respostas
  • 20 Views
Martin Hope
Razvan Zamfir
Asked: 2025-02-10 01:42:06 +0800 CST

Como posso exibir opções selecionadas de uma seleção múltipla neste aplicativo Laravel 8?

  • 5

Estou trabalhando em um aplicativo de blog no Laravel 8.

No formulário que uso para editar artigos, tenho um elemento de seleção múltipla.

Quero que o formulário mostre as tags que foram selecionadas. Para isso, fiz o seguinte na view:

<label for="tags" class="col-md-12">{{ __('Tags') }}</label>

@php
  $selected = explode(",", $tags);
@endphp

<select name="tags[]" id="tags" class="form-control" multiple="multiple">
    @foreach ($tags as $tag)
        <option value="{{ $tag->id }}" {{ (in_array($tag->id, $selected)) ? 'selected' : '' }}>{{ $tag->name }}</option>
    @endforeach
</select>

No controlador, tenho:

public function edit($id)
  {
    $article = Article::find($id);
    return view(
      'dashboard/edit-article',
      [
        'categories' => $this->categories(),
        'tags' => $this->tags(),
        'article' => $article
      ]
    );
  }

public function update(Request $request, $id)
{
    $validator = Validator::make($request->all(), $this->rules, $this->messages);

    if ($validator->fails()) {
      return redirect()->back()->withErrors($validator->errors())->withInput();
    }

    $fields = $validator->validated();
    $article = Article::find($id);

    // If a new image is uploaded, set it as the article image
    // Otherwise, set the old image...
    if (isset($request->image)) {
      $imageName = md5(time()) . Auth::user()->id . '.' . $request->image->extension();
      $request->image->move(public_path('images/articles'), $imageName);
    } else {
      $imageName = $article->image;
    }

    $article->title = $request->get('title');
    $article->short_description = $request->get('short_description');
    $article->category_id = $request->get('category_id');
    $article->featured = $request->has('featured');
    $article->image = $request->get('image') == 'default.jpg' ? 'default.jpg' : $imageName;
    $article->content = $request->get('content');
    // Save changes to the article
    $article->save();
    //Attach tags to article
    if ($request->has('tags')) {
      $article->tags()->attach($request->tags);
    }

    return redirect()->route('dashboard.articles')->with('success', 'The article titled "' . $article->title . '" was updated');
}

Por um motivo que não consegui identificar, isso não funciona. Isso significa que as tags do artigo não estão selecionadas no <select>elemento.

Onde está meu erro?

  • 1 respostas
  • 54 Views
Martin Hope
Razvan Zamfir
Asked: 2025-02-08 21:40:53 +0800 CST

Como posso usar um relacionamento muitos para muitos para exibir artigos por tag no Laravel?

  • 4

Estou trabalhando em um aplicativo de blog no Laravel 8 .

Estou tentando exibir artigos por tag na seguinte rota:

Route::get('/tag/{tag_id}', [ArticlesController::class, 'tag'])->name('tag');

No ArticlesControllercontrolador, tenho o tag()método que deve exibir todas as postagens que contêm uma determinada tag:

public function tag($tag_id)
{
    $tag   = Tag::firstWhere('id', $tag_id);
    $articles = Article::where('id', $tag->id)->orderBy('id', 'desc')->paginate($this->per_page);

    return view(
      'themes/' . $this->theme_directory . '/templates/index',
      array_merge($this->data, [
        'tag'   => $tag,
        'articles' => $articles
      ])
    );
}

Há um relacionamento muitos-para-muitos entre artigos e tags. Eu tenho uma article_tagtabela dinâmica:

insira a descrição da imagem aqui

No Tagmodelo eu tenho:

class Tag extends Model
{
   use HasFactory;

   protected $fillable = ['name'];

   public function article()
   {
       return $this->belongsToMany(Article::class);
   } 
}

Ao Articlemodelo adicionei o tags()método

public function tags()
{
    return $this->belongsToMany(Tag::class)->as('tags');
}

O problema

Exibe /tag/1apenas um artigo e esse artigo não contém uma tag com o id 1.

Questões:

  1. Onde está meu erro?
  2. Qual solução funcional requer alterações mínimas no código atual?
  • 2 respostas
  • 47 Views
Martin Hope
Razvan Zamfir
Asked: 2024-12-20 17:01:07 +0800 CST

Como posso implementar a contagem de linhas em DataTables quando os resultados são paginados?

  • 5

Eu uso DataTables para paginar e ordenar uma tabela contendo dados do usuário.

O conjunto de dados completo vem de um banco de dados MySQL por meio de um aplicativo .NET.

A primeira coluna da tabela tem que conter a contagem de linhas (atual) de uma maneira que tornaria a contagem "imune" à reorganização das linhas (classificação, em outras palavras). É por isso que usei uma contagem de linhas baseada em CSS, como visível abaixo:

new DataTable('#employees', {
  info: false,
  paging: true,
  "aLengthMenu": [5, 10, 20],
  // "dom": 'rtip',
});
.dt-column-order:before {
  margin-bottom: 1px;
}

th {
  outline: none !important;
}

.dt-paging {
  margin-top: 15px !important;
}

.pagination {
  justify-content: flex-end;
}

/* CSS row count */
table {
  counter-reset: row-num;
}

table tbody tr {
  counter-increment: row-num;
}

table tbody tr td:first-child::before {
  content: counter(row-num) "";
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js"></script>
<script src="https://cdn.datatables.net/2.1.8/js/dataTables.min.js"></script>
<script src="https://cdn.datatables.net/2.1.8/js/dataTables.bootstrap5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/2.1.8/css/dataTables.bootstrap5.min.css" rel="stylesheet" />

<div class="container-fluid my-2">
  <h2>Data Tables</h2>
  <table id="employees" class="table table-bordered table-striped mx-1">
    <thead>
      <tr>
        <th data-dt-order="disable">No</th>
        <th>Name</th>
        <th>Position</th>
        <th>Office</th>
        <th>Age</th>
        <th>Start date</th>
        <th>Salary</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td></td>
        <td>Tiger Nixon</td>
        <td>System Architect</td>
        <td>Edinburgh</td>
        <td>61</td>
        <td>2011-04-25</td>
        <td>$320,800</td>
      </tr>
      <tr>
        <td></td>
        <td>Garrett Winters</td>
        <td>Accountant</td>
        <td>Tokyo</td>
        <td>63</td>
        <td>2011-07-25</td>
        <td>$170,750</td>
      </tr>
      <tr>
        <td></td>
        <td>Ashton Cox</td>
        <td>Junior Technical Author</td>
        <td>San Francisco</td>
        <td>66</td>
        <td>2009-01-12</td>
        <td>$86,000</td>
      </tr>
      <tr>
        <td></td>
        <td>Cedric Kelly</td>
        <td>Senior Javascript Developer</td>
        <td>Edinburgh</td>
        <td>22</td>
        <td>2012-03-29</td>
        <td>$433,060</td>
      </tr>
      <tr>
        <td></td>
        <td>Ștefan Popa</td>
        <td>Accountant</td>
        <td>Tokyo</td>
        <td>33</td>
        <td>2008-11-28</td>
        <td>$162,700</td>
      </tr>
      <tr>
        <td></td>
        <td>Brielle Williamson</td>
        <td>Integration Specialist</td>
        <td>New York</td>
        <td>61</td>
        <td>2012-12-02</td>
        <td>$372,000</td>
      </tr>
      <tr>
        <td></td>
        <td>Herrod Chandler</td>
        <td>Sales Assistant</td>
        <td>San Francisco</td>
        <td>59</td>
        <td>2012-08-06</td>
        <td>$137,500</td>
      </tr>
      <tr>
        <td></td>
        <td>Rhona Davidson</td>
        <td>Integration Specialist</td>
        <td>Tokyo</td>
        <td>55</td>
        <td>2010-10-14</td>
        <td>$327,900</td>
      </tr>
      <tr>
        <td></td>
        <td>Colleen Hurst</td>
        <td>Javascript Developer</td>
        <td>San Francisco</td>
        <td>39</td>
        <td>2009-09-15</td>
        <td>$205,500</td>
      </tr>
      <tr>
        <td></td>
        <td>Sonya Frost</td>
        <td>Software Engineer</td>
        <td>Edinburgh</td>
        <td>23</td>
        <td>2008-12-13</td>
        <td>$103,600</td>
      </tr>
      <tr>
        <td></td>
        <td>Jena Gaines</td>
        <td>Office Manager</td>
        <td>London</td>
        <td>30</td>
        <td>2008-12-19</td>
        <td>$90,560</td>
      </tr>
      <tr>
        <td></td>
        <td>Quinn Flynn</td>
        <td>Support Lead</td>
        <td>Edinburgh</td>
        <td>22</td>
        <td>2013-03-03</td>
        <td>$342,000</td>
      </tr>
    </tbody>
  </table>
</div>

Porém, há um problema com essa solução: sempre que o conjunto de resultados for grande o suficiente para que haja paginação, a contagem de linhas começa em 1 para cada página.

Então, eu realmente preciso de uma contagem de linhas baseada em JavaScript, que não zeraria a contagem para cada página. Não encontrei uma maneira de fazer isso bult em DataTables.

Questões

  1. Existe uma solução integrada do DataTables para isso?
  2. Caso contrário, qual seria uma solução viável para o problema?
javascript
  • 3 respostas
  • 91 Views
Martin Hope
Razvan Zamfir
Asked: 2024-10-18 17:56:11 +0800 CST

O que causa essa falha ao filtrar uma tabela?

  • 4

Estou tentando filtrar uma tabela usando JavaScript simples.

Tenho uma entrada do tipo pesquisa e filtro as linhas da tabela pelo valor digitado nessa entrada.

function searchTable() {
  var input, filter, table, tr, tds, i, txt
  input = document.querySelector(".search-box")
  filter = input.value.toUpperCase()
  table = document.querySelector(".table-search")
  tr = table.querySelectorAll("tr")

  for (i = 0; i < tr.length; i++) {
    tds = Array.from(tr[i].getElementsByTagName("td"))

    if (tds.length) {
      tds.forEach(function(td) {
        txt = (td.textContent || td.innerText).toUpperCase()
        console.log(txt);
        if (!txt.includes(filter)) {
          console.log('hide')
          tr[i].classList.add("d-none")
        } else {
          console.log('show')
          tr[i].classList.remove("d-none")
        }
      })
    }
  }
}
.card-header {
  display: flex;
  align-items: center;
}

.search-box {
  border-color: #ccc !important;
  border-left: none;
  padding-left: 0;
}

.search-box:focus {
  box-shadow: none;
}

.btn-search {
  background: #fff !important;
  opacity: 1 !important;
  border-color: #ccc !important;
  border-right: none;
  padding-left: 10px;
  padding-right: 10px;
}

.table-heading {
  font-size: 1.25rem;
  font-weight: 700;
  margin: 0 15px 0 0;
  line-height: 1;
}

.table th {
  background: #f6f6f6;
}

.table > tbody > tr:nth-child(even of :not([class*="d-none"])) > td {
  background: #f6f6f6;
}

.sort-button {
  border-radius: 3px;
  background: #ccc;
  border: none;
}

.sort-button.active {
  background: #04aa6d;
  color: #fff;
}

.sort-button.desc {
  transform: rotateX(180deg);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<div class="container-fluid">
  <div class="card overflow-hidden shadow-sm my-2">
    <div class="card-header">
      <h2 class="table-heading">Users</h2>
      <div class="input-group input-group-prepend ms-auto w-75">
        <button class="btn btn-sm btn-search" type="button" disabled>
          <i class="fa-solid fa-magnifying-glass"></i>
        </button>
        <input type="search" class="form-control form-control-sm search-box" placeholder="Search" onkeyup="searchTable()" />
      </div>
    </div>
    <div class="card-body p-0">
      <table class="table table-search m-0">
        <thead>
          <tr>
            <th>Firstname</th>
            <th>Lastname</th>
            <th>Age</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td class="fname">Alan</td>
            <td class="lname">Green</td>
            <td class="age">24</td>
          </tr>
          <tr>
            <td class="fname">Anne</td>
            <td class="lname">Smith</td>
            <td class="age">42</td>
          </tr>
          <tr>
            <td class="fname">Jane</td>
            <td class="lname">Doe</td>
            <td class="age">19</td>
          </tr>
          <tr>
            <td class="fname">July</td>
            <td class="lname">Dooley</td>
            <td class="age">121</td>
          </tr>
          <tr>
            <td class="fname">Mary</td>
            <td class="lname">Moe</td>
            <td class="age">21</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

Por um motivo que não consegui identificar, independentemente de a sequência de pesquisa exibir algum resultado ou não, todas as linhas ficam ocultas.

Onde está meu erro?

javascript
  • 2 respostas
  • 52 Views
Martin Hope
Razvan Zamfir
Asked: 2024-09-25 20:18:28 +0800 CST

Como selecionar linhas de tabela que sejam simultaneamente pares e exibidas?

  • 7

Tenho uma tabela HTML com linhas ímpares coloridas em cinza.

Algumas linhas estão ocultas <tr style="display: none">e isso cria a possibilidade de duas linhas exibidas consecutivamente serem da mesma cor, como visto no recorte abaixo:

.table thead th{
   background: #f6f6f6;
}

.table>tbody>tr:nth-of-type(even)>td {
  background: #f6f6f6;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>


<table class="table">
    <thead>
      <tr>
        <th>Firstname</th>
        <th>Lastname</th>
        <th>Email</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>John</td>
        <td>Doe</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>Jane</td>
        <td>Doe</td>
        <td>[email protected]</td>
      </tr>
      <tr style="display: none">
        <td>Mary</td>
        <td>Moe</td>
        <td>[email protected]</td>
      </tr>
      <tr>
        <td>July</td>
        <td>Dooley</td>
        <td>[email protected]</td>
      </tr>
    </tbody>
  </table>

Isso significa que preciso de uma maneira de selecionar todas as linhas que são ímpares e não têm style="display: none".

Como posso alcançar esse resultado?

html
  • 2 respostas
  • 41 Views
Martin Hope
Razvan Zamfir
Asked: 2024-08-26 21:05:25 +0800 CST

Como posso fechar o menu suspenso programaticamente ao clicar no botão?

  • 5

Eu tenho o menu suspenso Bootstrap 5 abaixo de caixas de seleção rotuladas , com data-bs-auto-close="outside", para que o menu feche com um clique externo.

<div class="dropdown">
  <button type="button" class="btn btn-success dropdown-toggle" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
    Dropdown button
  </button>
  <div class="dropdown-menu">
    <div class="px-1">
      <input class="form-check-input" type="checkbox" id="option1" name="filter">
      <label for="option1">Option 1</label>
    </div>

    <div class="px-1">
      <input class="form-check-input" type="checkbox" id="option2" name="filter">
      <label for="option2">Option 2</label>
    </div>

    <div class="btn-group px-1 mt-2 w-100">
      <button onclick="closeFilter()" type="button" class="apply btn btn-sm btn-success">Apply</button>
      <button onclick="closeFilter()" type="button" class="reset btn btn-sm btn-success">Reset</button>
    </div>
  </div>
</div>

Quero que o menu feche quando qualquer um dos botões "Aplicar" e "Redefinir" for clicado. Para isso, tenho a função abaixo:

function closeFilter() {
  let dropDown = event.target.closest('.dropdown');
  let dropDownButton = dropDown.querySelector('.dropdown-toggle');
  dropDownButton.style.border = '1px solid red';
  dropDownButton.dropdown('toggle');
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<div class="dropdown">
  <button type="button" class="btn btn-success dropdown-toggle" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
    Dropdown button
  </button>
  <div class="dropdown-menu">
    <div class="px-1">
      <input class="form-check-input" type="checkbox" id="option1" name="filter">
      <label for="option1">Option 1</label>
    </div>

    <div class="px-1">
      <input class="form-check-input" type="checkbox" id="option2" name="filter">
      <label for="option2">Option 2</label>
    </div>

    <div class="btn-group px-1 mt-2 w-100">
      <button onclick="closeFilter()" type="button" class="apply btn btn-sm btn-success">Apply</button>
      <button onclick="closeFilter()" type="button" class="reset btn btn-sm btn-success">Reset</button>
    </div>
  </div>
</div>

No entanto, a função acima gera o erro:

dropDownButton.dropdown is not a function

Onde está o meu erro?

javascript
  • 2 respostas
  • 40 Views
Martin Hope
Razvan Zamfir
Asked: 2024-05-21 19:23:37 +0800 CST

Como isolar uma chamada de API para um único componente neste aplicativo Angular 16?

  • 7

Tenho trabalhado em um SPA com Angular 16, TypeScript e The Movie Database (TMDB).

Encontrei um problema após o desenvolvimento de um recurso de "rolagem infinita".

No MoviesByGenrecomponente eu tenho:

import { Component } from '@angular/core';
import { GenreResponse, Genre } from '../../models/Genre';
import { MovieResponse, Movie } from '../../models/Movie';
import { MovieService } from '../../services/movie-service.service';
import { ActivatedRoute } from '@angular/router';
import { distinctUntilChanged, fromEvent, map, startWith } from 'rxjs';

@Component({
  selector: 'app-movies-by-genre',
  templateUrl: './movies-by-genre.component.html',
  styleUrls: ['./movies-by-genre.component.scss']
})

export class MoviesByGenre {
  constructor(
    private activatedRoute: ActivatedRoute,
    private movieService: MovieService
  ) { }

  public genreName: string | undefined = '';
  public movieResponse!: MovieResponse;
  public movies: Movie[] = [];
  public genreResponse!: GenreResponse;
  public genres: Genre[] | undefined = [];
  public genreId!: number;
  public maxPage: number = 10;
  public pageNumber: number = 1;
  public isLoading: boolean = false;

  public getMoviesByGenre(): void {
    // Get genre id (from URL parameter)
    this.genreId = Number(this.activatedRoute.snapshot.paramMap.get('id'));

    // Get genre name from genres array
    this.movieService.getAllMovieGenres().subscribe((response) => {
      this.genreResponse = response;
      this.genres = this.genreResponse.genres;

      if (this.genres && this.genres.length) {
        let currentGenre = this.genres.find(
          (genre) => genre.id === this.genreId
        );
        if (currentGenre) {
          this.genreName = currentGenre.name || '';
          this.movieService.defaultTitle = this.genreName;
        }
      }
    });

    this.loadMoreMovies(this.genreId, this.pageNumber);
  }

  public loadMoreMovies(genreId: number, pageNumber: number) {
    // Get movies by genre id
    this.movieService
      .getMoviesByGenre(genreId, pageNumber)
      .subscribe((response) => {
        this.movieResponse = response;
        this.movies.push(...(this.movieResponse?.results || []));
      });
  }

  ngAfterViewInit() {
    fromEvent(window, 'scroll')
      .pipe(
        startWith(0),
        map(() => window?.scrollY),
        distinctUntilChanged()
      )
      .subscribe((scrollPos: any) => {
        if (!this.movies?.length) {
          return;
        }
        if (
          Math.round(scrollPos + window.innerHeight) >=
          document.documentElement.scrollHeight &&
          this.pageNumber < this.maxPage
        ) {
          this.pageNumber++;
          this.loadMoreMovies(this.genreId, this.pageNumber);
        }
      });
  }

  ngOnInit() {
    this.activatedRoute.params.subscribe(() => {
      this.movies = [];
      this.getMoviesByGenre();
    });
  }

  ngOnDestroy() {
    this.movieService.defaultTitle = '';
  }
}

No MovieServiceserviço:

import { environment } from '../../environments/environment';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { MovieResponse, Movie } from '../models/Movie';
import { GenreResponse } from '../models/Genre';
import { TrailerResponse } from '../models/Trailer';

@Injectable({
  providedIn: 'root'
})

export class MovieService {

  constructor(private http: HttpClient) { }

  public defaultTitle: string = '';


  public getAllMovieGenres(): Observable<GenreResponse> {
    return this.http.get<GenreResponse>(`${environment.apiUrl}/genre/movie/list?api_key=${environment.apiKey}`);
  }

  public getMoviesByGenre(id: Number, pageNumber: Number): Observable<MovieResponse> {
    return this.http.get<MovieResponse>(`${environment.apiUrl}/discover/movie?api_key=${environment.apiKey}&with_genres=${id}&page=${pageNumber}`);
  }

  public getMovieDetails(id: Number): Observable<Movie>{
    return this.http.get<Movie>(`${environment.apiUrl}/movie/${id}?api_key=${environment.apiKey}`);
  }
}

A cada rolagem até o final da página do by-genre/:idpercurso, são carregados mais 20 filmes, com limite definido em 10 páginas (200 filmes).

O problema

O problema é que mesmo em outras rotas, como a rota de detalhes do filme, uma chamada de API é feita ao rolar até o final da página e mostra o botão giratório de carregamento, para o qual usei uma técnica de interceptador http , desnecessariamente.

O objetivo

O objetivo é tornar a rolagem infinita específica para o MoviesByGenrecomponente:

Para isso, adicionei um booleano ao MoviesByGenrecomponente e utilizei-o da seguinte forma:

public isLoadMore: boolean = true;

if (this.isLoadMore) {
  this.loadMoreMovies(this.genreId, this.pageNumber);
} 

Mas as solicitações ainda são feitas em outros componentes ao rolar até o final da página.

Parece que falhei em identificar a causa do problema e em fornecer uma solução viável .

Questões

  1. O que causa esse problema?
  2. Qual é a maneira mais confiável de consertar isso?
javascript
  • 1 respostas
  • 43 Views
Martin Hope
Razvan Zamfir
Asked: 2024-05-08 05:22:22 +0800 CST

O que causa a falha na exibição deste girador de carregamento Angular 16?

  • 5

Estou criando um "spinner de carregamento" em nível de aplicativo com a ajuda do HttpInterceptorAngular 16.

Em app\services\interceptor.service.tseu tenho:

import { Injectable } from '@angular/core';
import { HttpInterceptor,HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';
import { finalize } from 'rxjs/operators';
import { SpinnerService } from './spinner.service';


@Injectable({
  providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {
  constructor(private spinnerService: SpinnerService) { }

  public intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    this.spinnerService.show();
    return next.handle(req).pipe(
      finalize(() => {
        this.spinnerService.hide();
      })
    );
  }
}

Em app\services\spinner.service.ts:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SpinnerService {
  private spinnerCounter = new BehaviorSubject<number>(0);
  spinnerCounter$ = this.spinnerCounter.asObservable();

  public show() {    
    this.spinnerCounter.next(this.spinnerCounter.value + 1);
  }

  public hide() {    
    this.spinnerCounter.next(this.spinnerCounter.value - 1);
  }
}

Eu importei o spinnerServicein app\app.component.tse adicionei o spinner ao arquivo app\app.component.html.

<app-loading-spinner *ngIf="spinnerService.spinnerCounter$ | async"></app-loading-spinner>

Stackblitz

O app-loading-spinnercomponente nunca é exibido entre solicitações HTTP. O que estou fazendo de errado e como posso corrigir esse problema?

javascript
  • 1 respostas
  • 32 Views
Martin Hope
Razvan Zamfir
Asked: 2024-04-21 04:11:19 +0800 CST

O que faz com que a propriedade não exista no erro de tipo neste aplicativo Angular 16 filmes?

  • 6

Tenho trabalhado em um SPA com Angular 16, TypeScript e The Movie Database (TMDB).

Tenho um problema ao trabalhar na exibição dos detalhes de um filme.

Em app\services\movie-service.service.tseu tenho:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';
import { HttpClient } from '@angular/common/http';
import { MovieResponse } from '../models/Movie';
import { Genre, GenreResponse } from '../models/Genre';

@Injectable({
  providedIn: 'root'
})

export class MovieService {

  constructor(private http: HttpClient) { }


  public getLatestMovies(): Observable<MovieResponse> {
    return this.http.get<MovieResponse>(`${environment.apiUrl}/movie/now_playing?api_key=${environment.apiKey}`);
  }

  public getMovieDetails(id: Number): Observable<MovieResponse>{
    return this.http.get<MovieResponse>(`${environment.apiUrl}/movie/${id}?api_key=${environment.apiKey}`);
  }
}

Em app\models\Movie.tseu tenho:

export interface Movie {
    id?: number;
    adult?: boolean;
    backdrop_path?: string;
    poster_path?: string;
    title?: string;
    original_title?: string;
    tagline?: string;
    overview?: string;
    genre_ids?: any;
    release_date?: string;
    runtime?: number;
    vote_average?: string;
}

export interface MovieResponse {
    results?: Movie[];
    total_pages?: number;
    total_results?: number;
    page?: number;
}

Em app\components\movie-details\movie-details.component.tseu tenho:

import { Component } from '@angular/core';
import { MovieResponse, Movie } from '../../models/Movie';
import { MovieService } from '../../services/movie-service.service';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-movie-details',
  templateUrl: './movie-details.component.html',
  styleUrls: ['./movie-details.component.scss']
})
export class MovieDetailsComponent {

  constructor(private movieService: MovieService, private activatedRoute: ActivatedRoute) { }

  public movieResponse!: MovieResponse;
  public movie_id: Number = 0;

  public showMovieDetails() {
    this.movie_id = Number(this.activatedRoute.snapshot.paramMap.get('id'));

    this.movieService.getMovieDetails(this.movie_id).subscribe((response) => {
      this.movieResponse = response;
    });
  }

  ngOnInit() {
    this.showMovieDetails();
  }
}

Em app\components\movie-details\movie-details.component.htmltento exibir o título do filme:

<div *ngIf="movieResponse">
  <h1>{{ movieResponse?.original_title }}</h1>
</div>

O problema

Insted do resultado desejado, recebo este erro no navegador:

TS2339: Property 'original_title' does not exist on type 'MovieResponse'.

Questões

  1. O que estou fazendo de errado?
  2. Qual é a maneira mais confiável de corrigir esse problema?
javascript
  • 1 respostas
  • 20 Views
Martin Hope
Razvan Zamfir
Asked: 2024-04-20 14:50:11 +0800 CST

O que faz com que a propriedade 'resultados' não exista no erro de tipo neste aplicativo Angular 16?

  • 6

Tenho trabalhado em um SPA com Angular 16, TypeScript e The Movie Database (TMDB).

Em app\services\movie-service.service.tseu tenho:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';
import { HttpClient } from '@angular/common/http';
import { MovieResponse, Movie } from '../models/Movie';

@Injectable({
  providedIn: 'root'
})

export class MovieService {

  constructor(private http: HttpClient) { }

  public getMovies(): Observable<MovieResponse[]> {
    return this.http.get<MovieResponse[]>(`${environment.apiUrl}/movie/now_playing?api_key=${environment.apiKey}`);
  }
}

O modelo app\models\Movie.tsfica assim:

export interface Movie {
    id?: number;
    adult?: boolean;
    backdrop_path?: string;
    poster_path?: string;
    title?: string;
    tagline?: string;
    overview?: string;
    genre_ids?: any;
    original_title?: string;
    release_date?: string;
    runtime?: number;
    vote_average?: string;
}

export interface MovieResponse {
    results?: Movie[];
    total_pages?: number;
    total_results?: number;
    page?: number;
}

No HomePageComponenteu tento produzir os filmes:

import { Component } from '@angular/core';
import { MovieResponse, Movie } from '../../models/Movie';
import { MovieService } from '../../services/movie-service.service';


@Component({
  selector: 'app-home-page',
  templateUrl: './home-page.component.html',
  styleUrls: ['./home-page.component.scss']
})
export class HomePageComponent {

  public movieResponse!: MovieResponse[];

  public movies: Movie[] = [];

  constructor(private movieService: MovieService) { }

  public getMovies() {
    this.movieService.getMovies().subscribe((response) => {
      this.movieResponse = response;

      console.log(this.movieResponse);

      this.movies = this.movieResponse.results;
    })
  }

  ngOnInit() {
    this.getMovies();
  }
}

A linha console.log(this.movieResponse)mostra basicamente a resposta com o resultsarário, total_pages, etc;

O problema

A linha this.movies = this.movieResponse.resultscausa o erro:

TS2339: Property 'results' does not exist on type 'MovieResponse[]'.

Questões

  1. O que estou fazendo de errado?
  2. Qual é a maneira mais confiável de corrigir esse problema?
javascript
  • 1 respostas
  • 28 Views
Martin Hope
Razvan Zamfir
Asked: 2024-02-20 23:15:28 +0800 CST

O que causa a falha na renderização de uma matriz de objetos neste aplicativo Firebase e React?

  • 5

Estou trabalhando em um aplicativo de chat com Firebase 9 e React 18.

O UserItem.jsxcomponente fica assim:

export default function UserItem({ user }) {
  return (
    <>
      <li className="d-table-row w-100">
        <div className="user-image-container d-table-cell">
          <img src={user?.avatar} alt={`${user?.firstName} ${user?.lastName}`} className="rounded-circle" />
        </div>
        <div className="text d-table-cell">
          <h3 className="display-name m-0">{user.firstName} {user.lastName}</h3>
        </div>
      </li>
    </>
  )
}

O UsersList.jsxcomponente deve exibir o usuário com o firstNameJohn:

export default function UsersList() {

  const location = useLocation();
  const [users, setUsers] = useState([]);
  const [err, setErr] = useState(false);

  const getUsers = async () => {

    const q = query(collection(db, "users"), (where('firstName', '==', 'John'),   
      or(
        where('lastName', '==', 'Doe'),
        where('email', '==', '[email protected]')
      )));

     try {
        const querySnapshot = await getDocs(q);
        querySnapshot.forEach((doc) => {
          if (doc.data() !== null) {
            users.push(doc.data());
          } 
          setUsers(users);
          console.log(users);
        });
      } catch (err) {
        setErr(true);
      }
  }

  const usersList = () => {
    return users.map(user => (
      <UserItem
        key={user.uid}
        user={user}
      />
    ))
  }

  useEffect(() => {
    getUsers();
  }, [location, setUsers])

  return (
    <div className="chat-users">
      {!users.length ? <p className="m-0 text-center text-danger">No users found</p> : 
        <PerfectScrollbar>
          <ul className="users-list list-unstyled m-0 d-table w-100">
            {usersList()}
          </ul>
        </PerfectScrollbar>
      }
    </div>
  );
}

          

O problema

Embora Evan console.log(users) exiba uma série de usuários no console do Chrome, a lista de usuários não é exibida, mas em vez disso "Nenhum usuário encontrado" é visível, como se não houvesse usuários.

Questões:

  1. O que causa o problema descrito?
  2. Qual é a maneira mais confiável de consertar isso?
  • 1 respostas
  • 49 Views
Martin Hope
Razvan Zamfir
Asked: 2023-09-24 19:19:37 +0800 CST

Como confirmo a senha em formulários React com Simple Body Validator? [duplicado]

  • 4
Esta pergunta já tem respostas aqui :
Como obtenho validação instantânea de campos de formulário neste aplicativo React 18? (3 respostas)
Fechado há 7 horas .

Estou trabalhando em um aplicativo de chat com React 18 e Firebase.

No src\pages\Register.jsxcomponente, tenho um formulário que valido com Simple Body Validator :

import React, { useState } from "react";
import FormCard from "../components/FormCard/FormCard";
import { make } from "simple-body-validator";

export default function Register() {
  const initialFormData = {
    firstName: "",
    lastName: "",
    email: "",
    password: "",
    password_confirmation: ""
  };

  const validationRules = {
    firstName: ["required", "string", "min:3", "max:255"],
    lastName: ["required", "string", "min:3", "max:255"],
    email: ["required", "email"],
    password: ["required"],
    password_confirmation: ["required"]
  };

  const validator = make(initialFormData, validationRules);
  const [formData, setFormData] = useState(initialFormData);
  const [errors, setErrors] = useState(validator.errors());

  const [pristineFields, setPristineFields] = useState(() =>
    Object.keys(initialFormData)
  );

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData((prevFormData) => {
      const newFormData = { ...prevFormData, [name]: value };
      const newPristineFields = pristineFields.filter((f) => f !== name);

      validator.setData(newFormData).validate();
      const validationErrors = validator.errors();
      newPristineFields.forEach((f) => validationErrors.forget(f));
      setErrors(validationErrors);

      setPristineFields(newPristineFields);

      return newFormData;
    });
  };

  const handleSubmit = (event) => {
    event.preventDefault();

    if (!validator.setData(formData).validate()) {
      setErrors(validator.errors());
    }

    setPristineFields([]);
  };

  return (
    <FormCard title="Register">
      <form onSubmit={handleSubmit}>
        <div
          className={`mb-2 form-element ${errors.has("firstName") ? "has-error" : null
            }`}
        >
          <label for="firstName" className="form-label">
            First name
          </label>
          <input
            type="text"
            id="firstName"
            name="firstName"
            value={formData.firstName}
            onChange={handleChange}
            className="form-control form-control-sm"
          />
          {errors.has("firstName") ? (
            <p className="invalid-feedback">{errors.first("firstName")}</p>
          ) : null}
        </div>

        <div
          className={`mb-2 form-element ${errors.has("lastName") ? "has-error" : null
            }`}
        >
          <label for="lastName" className="form-label">
            Last name
          </label>
          <input
            type="text"
            id="lastName"
            name="lastName"
            value={formData.lastName}
            onChange={handleChange}
            className="form-control form-control-sm"
          />
          {errors.has("lastName") ? (
            <p className="invalid-feedback">{errors.first("lastName")}</p>
          ) : null}
        </div>

        <div
          className={`mb-2 form-element ${errors.has("email") ? "has-error" : null
            }`}
        >
          <label for="email" className="form-label">
            Email address
          </label>
          <input
            type="email"
            id="email"
            name="email"
            value={formData.email}
            onChange={handleChange}
            className="form-control form-control-sm"
          />
          {errors.has("email") ? (
            <p className="invalid-feedback">{errors.first("email")}</p>
          ) : null}
        </div>

        <div
          className={`mb-2 form-element ${errors.has("password") ? "has-error" : null
            }`}
        >
          <label for="password" className="form-label">
            Password
          </label>
          <input
            type="password"
            id="password"
            name="password"
            value={formData.password}
            onChange={handleChange}
            className="form-control form-control-sm"
          />
          {errors.has("password") ? (
            <p className="invalid-feedback">{errors.first("password")}</p>
          ) : null}
        </div>

        <div
          className={`mb-2 form-element ${errors.has("password_confirmation") ? "has-error" : null
            }`}
        >
          <label for="password_repeat" className="form-label">
            Confirm Password
          </label>
          <input
            type="password"
            id="password_repeat"
            name="password_confirmation"
            value={formData.password_confirmation}
            onChange={handleChange}
            className="form-control form-control-sm"
          />
          {errors.has("password_confirmation") ? (
            <p className="invalid-feedback">
              {errors.first("password_confirmation")}
            </p>
          ) : null}
        </div>

        <div className="pt-1">
          <button type="submit" className="btn btn-sm btn-success fw-bold">
            Submit
          </button>
        </div>
      </form>
    </FormCard>
  );
}

O problema

De acordo com meu entendimento dos documentos, a biblioteca de validação requer um campo password_confirmation para o campo Confirmar senha .

Mas se passworde password_confirmationnão corresponderem (por exemplo: "123" para senha e "1234" para senha_confirmação), não há erros de validação.

Questões

  1. O que estou fazendo de errado?
  2. Qual é a maneira mais confiável de corrigir o problema?
javascript
  • 1 respostas
  • 32 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve