NullInjectorError: No provider for Renderer2! en un Service de Angular

Si intentamos manipular el DOM desde un servicio de Angular (a sabiendas que no es aconsejado según las convenciones de Angular) es posible que nos salte el error:

NullInjectorError: No provider for Renderer2

Si queremos romper las «reglas» y acceder al DOM podemos hacer una truquito mientras Angular arregla el issue (https://github.com/angular/angular/issues/17824)

Lo que podemos hacer es inyectar en el constructor «RendererFactory2» y asignar en el constructor el «rendererFactory» inyectado a la propiedad «_renderer2» que anteriormente hemos inicializado.

El ejemplo entero:

import { Injectable, Renderer2, RendererFactory2 } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AccesoDomDesdeService {

  private _renderer2: Renderer2

  constructor(
    rendererFactory: RendererFactory2,
  ) { 
    this._renderer2 = rendererFactory.createRenderer(null, null)
  }

}

Y ya podríamos utilizar el «_renderer2» para acceder al DOM perfectamente.


Tu opinión es importante para mi, ¿Te ha resultado útil este artículo?

Añadir directorio para albergar una landing dentro de un proyecto Angular

No es lo más bonito, limpio, etc, etc… Pero, si queremos albergar una web/landing/blog o simplemente un directorio para tener algunos recursos dentro de nuestro proyecto en Angular

{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    ...
    "projects": {
      "webapp": {
        ...
        "architect": {
          "build": {
            "builder": "@angular-devkit/build-angular:browser",
            "options": {
              ...
              "assets": [
                "src/favicon.ico.png",
                "src/assets",
                "src/landing"
              ]
          }
        }
      }
    }
  }
}

Creamos una carpeta con el mismo nombre que hemos puesto «landing» y creamos un index.html dentro.


Y ya, compilamos y ya podemos acceder a:

http://localhost:4200/landing

Y veremos el index que hemos creado (:


Tu opinión es importante para mi, ¿Te ha resultado útil este artículo?

Validar que el campo no exista en base de datos ignorando el del propio usuario con Laravel Validators

El título nos puede marear un poco, no supe resumirlo.

Básicamente, si queremos validar que el campo no exista en base datos, desde un validator de Laravel pondremos algo parecido a:
(pongamos el ejemplo que tenemos un campo que se llama usuario/username en base datos que queramos que sea único)

Este sería un resumen el archivo App\Http\Requests\UpdateUserRequest.php

class UpdateUserRequest extends FormRequest
{
    ...
    public function rules()
    {
        return [
            ...
            'surnames' => 'string|max:150',
            'username' => 'string|max:30|unique:users,username',
            ...
        ];
    }
}

Si nos fijamos en el campo username, entre otras validaciones (que sea un string como máximo 30 caracteres) tenemos unique, junto con la tabla; users y el campo que queremos que sea único; username.

Bien, esto nos funcionaría la primera vez cuando el usuario todavía no tiene un username… pero cuando vamos a actualizar el campo vamos a tener el problema que esta validación no nos permitiría enviar nuestro propio nombre de usuario ya que detectaría que ya existe en base de datos y nos lo echaría atrás.

En este caso tenemos que utilizar un validation rule diciéndole que ignore el username que esté relacionado con nuestro usuario (en este caso, el usuario logueado «request()->user()->id «):

public function rules()
class UpdateUserRequest extends FormRequest
{
    ...
    public function rules()
    {
        return [
            ...
            'surnames' => 'string|max:150',
            'username' => [ 'string', 'max:30', ValidationRule::unique( 'users' )->ignore( request()->user()->id ) ],
            ...
        ];
    }
}

¡Espero que os sirva!
Saludos 👨‍💻


Tu opinión es importante para mi, ¿Te ha resultado útil este artículo?

La guía (cheat sheet) definitiva de Grid CSS

En el post anterior os pasé un par de enlaces para ver qué es CSS GRID y para empezar a aprender.

En este os paso un par de enlaces a modo de chuleta para refrescar la cantidad de propiedades que tiene CSS GRID.

Aquí tenemos dos páginas de referencia para (de un plumazo) refrescar la memoria de las bondades que atesora.

https://learncssgrid.com

https://grid.malven.co


Captura de pantalla de grid.malven.com


Tu opinión es importante para mi, ¿Te ha resultado útil este artículo?

Ir a un anchor/punto de ancla con un margen superior personalizado

A veces cuando nos queremos mover a un punto de «ancla» nos puede surgir un problema en el caso que tengamos, por ejemplo, un navbar.
¿Por qué? Porque HTML no reconoce si tiene una capa que le tape cierto contenido o no. Para solucionar esto tenemos una propiedad en css llamada scroll-margin-top, y le podemos pasar los píxeles de margen que queremos respecto a la parte superior.

#elemento{
    scroll-margin-top: 72px;
}

Podemos ver el ejemplo en Codepen:

See the Pen
Scroll to Anchor with margin top
by Kike (@kikebeltran)
on CodePen.


Tu opinión es importante para mi, ¿Te ha resultado útil este artículo?

Expected validator to return Promise or Observable

Si te retorna este error en Angular es porque tendrás más de un «validator» sin que estén dentro de un array.

Por ejemplo:

this.formBuilder.group({
    ...
    email: ['', Validators.required, Validators.email],
});

Si tienes varios «Validators» sin que estos estén contenidos en su propio array, deberíamos modificarlos a:

this.formBuilder.group({
    ...
    email: ['', [Validators.required, Validators.email] ],
});

Y fixed 💃


Pasamos de tener los «Validators» de:

Validators.required, Validators.email

a:

[ Validators.required, Validators.email ]


Tu opinión es importante para mi, ¿Te ha resultado útil este artículo?

Crear el Model, Factory, Migration, Seeder y Controller con un solo comando en Laravel 8

Si estamos trabajando en Laravel 8 y queremos crear todos estos archivos:

Model
Factory
Migration
Seeder
Controller

Tan solo tendremos que ejecutar:

php artisan make:model ModelName -a

Nos devolverá:

Model created successfully.
Factory created successfully.
Created Migration: 2021_06_30_063551_create_name_table
Seeder created successfully.
Controller created successfully.

Tu opinión es importante para mi, ¿Te ha resultado útil este artículo?

sequelize.query() devuelve dos veces el mismo resultado

Pongamos, por ejemplo que tenemos esta simple consulta:

const sessions = await Session.sequelize?.query( 'SELECT * FROM sessions' )

En este caso la constante sessions será algo como:

[
    {
        "id": "",
        "createdAt": "",
        ...
    },
    {
        "id": "",
        "createdAt": "",
        ...
    },
    ...
],
[
    {
        "id": "",
        "createdAt": "",
        ...
    },
    {
        "id": "",
        "createdAt": "",
        ...
    },
    ...
]

Esto se debe a que nos está devolviendo metadata (que en el caso de mysql no afecta, son dos arrays iguales).

Para evitar que nos devuelva dos arreglos tenemos que pasarle a la consulta el parámetro:

{ type: QueryTypes.SELECT }
// O, depende de la importación que tengamos
{ type: Sequalize.QueryTypes.SELECT }

como argumento a «query«.

Con lo que la consulta nos quedaría algo parecido a:

const sessions = await Session.sequelize?.query( 
    'SELECT * FROM sessions',
    { type: QueryTypes.SELECT }
)

Happy code 👨‍💻🎉


Tu opinión es importante para mi, ¿Te ha resultado útil este artículo?