Aprende a mostrar estados de cercanía de forma clara con Angular. Aquí verás cómo combinar ngSwitch (directiva de atributo) con ngSwitchCase (directiva estructural) y ngStyle para renderizar un único label por elemento y colorearlo según el nivel. Todo parte de un modelo con datos calculados en el servidor, eficiente para múltiples clientes.
¿Qué resuelve ngSwitch en una lista con cercanía?
La vista debe indicar si un lugar está muy cercano, cercano o lejano. Para ello, cada elemento tiene dos atributos definidos en el servidor: cercanía (niveles 1, 2, 3; 1 es más cercano, 3 más lejano) y distancia en kilómetros. El cálculo en el servidor es clave: se procesa una vez y queda disponible para un cliente de Angular, uno móvil o de escritorio. Así se mantiene consistencia y rendimiento.
Un único estado visible por lugar: muy cercano, cercano o lejano.
Niveles de cercanía: 1, 2 y 3; 1 es el más cercano.
Distancia en km como dato auxiliar: 1, 1.8, 5, 10, 35, 120.
Beneficio del servidor: cálculo centralizado para todos los clientes.
Habilidades: elegir directiva correcta, modelar atributos, y comunicar estados con claridad.
¿Cómo luce el modelo de datos?
Atributos por lugar: cercania (1–3). distancia (km).
El servidor entrega estos campos ya calculados.
La interfaz solo consume y muestra.
¿Cómo implementar ngSwitch y ngSwitchCase en Angular?
La directiva [ngSwitch] evalúa un valor y muestra solo el caso que coincide. Según se explica, no evalúa expresiones: debe haber un matching exacto o caer en un caso por defecto (default).
[ngSwitch]: directiva de atributo que decide el valor a evaluar.
*ngSwitchCase: directiva estructural que agrega o remueve del DOM.
Estrategia: evaluar lugar.cercania y mostrar un único label.
<!-- lista de lugares --><div*ngFor="let lugar of lugares"><div[ngSwitch]="lugar.cercania"><span*ngSwitchCase="1">Muy cercano</span><span*ngSwitchCase="2">Cercano</span><span*ngSwitchCase="3">Lejano</span><!-- Si no hay coincidencia exacta, se usaría un caso por defecto. --></div></div>
Buenas prácticas.
Mantén el valor de [ngSwitch] simple: lugar.cercania.
Usa casos explícitos 1, 2 y 3.
Recuerda que solo se muestra un caso a la vez.
¿Cómo combinar ngSwitch con ngStyle para dar feedback visual?
Para reforzar la lectura visual, se colorean los labels: verde para “Muy cercano”, negro para “Cercano” y rojo para “Lejano”. Importante en ngStyle: la evaluación debe ser un objeto entre llaves, de lo contrario verás un error en el navegador tras un refresh.
<div*ngFor="let lugar of lugares"><div[ngSwitch]="lugar.cercania"><span*ngSwitchCase="1"[ngStyle]="{ color: 'green' }">Muy cercano</span><span*ngSwitchCase="2"[ngStyle]="{ color: 'black' }">Cercano</span><span*ngSwitchCase="3"[ngStyle]="{ color: 'red' }">Lejano</span></div></div>
Claves de implementación.
ngStyle es de atributo: espera un objeto con pares propiedad-valor.
color como propiedad CSS: 'green', 'black', 'red'.
Si olvidas las llaves en ngStyle, se produce un error.
¿Te gustaría ver un caso adicional por defecto o variar estilos según distancia? Cuéntalo en los comentarios y qué otros indicadores visuales usarías.
Hola @aleehpandita, “deja tu lo interesante” te refieres a compartir el código del ejemplo y sus variantes en un repositorio?, de ser el caso con gusto lo hago.
Parte de mi filosofía como estudiante es incentivar/proponer a los compañeros actividades asociadas a los ejercicios de los cursos, no solo Angular, muchos tenemos una cuenta en Digitalocean u otro proveedor donde se podrían desplegar apps interesantes la cual sería la suma de todas esas partes (aportes de compañeros Platzi, grupos de estudio).
Quien comparta esa misma filosofía o método de estudio con gusto recibo el feedback u opiniones para comenzar inmediatamente con proyecto de este curso de Angular 4 para llevarlo a PRO.
Quedo pendiente de quien quiera participar en este proyecto para el Curso, ()
Sería interesante también que por cada Fork o mejora de un estudiante dado en un repositorio (grupo de estudio), sumen unos 100 puntos del Platzi Rank (o como lo ponderen)
Saludos @teamPlatzi, les agradezco sinceramente que lo tengan en cuenta y guste la idea.
En los casos en los cuales no se tenga que evaluar nada en las directivas ngStyle y ngClass, no sería mejor solo utilizar los atributos style y class de siempre? o es una buena práctica de Angular, o da igual y solo lo usas por fines prácticos del curso?
Genial, hasta ahora para estos casos yo usaba una funcion que definia en el componente y hacia el switch a nivel de Js
Por ejemplo
{{getCargo(personal.cargo)}}
Y en el componente
getCargo(cargo){switch(cargo){case...}return...}
Esto en AngularJS me traía problemas porque se ejecutaba constantemente volviendo pesada la aplicación.
En angular 4 que es con el que actualmente trabajo no he revisado el caso.
Pero acabo de aprender esta nueva directiva.
En javascript switch funciona con enteros, decimales (floats), strings y booleanos; o sea, con todos los tipos primitivos. Cómo Angular está escrito en javascript supongo que será igual, pero no lo he probado.
<p [ngSwitch]="valorencomponentedeswitch"><template [ngSwitchCase]="1">FormaSwitch2</template><template [ngSwitchCase]="2">FormaSwitch 2a</template><template [ngSwitchCase]="5">FormaSwitch 2b</template><template ngSwitchDefault>FormaSwitch 2v</template></p>Donde template es palabra reservada, y ngSwitchDefault es directo sin Corchetes
<!-- lista de lugares completa --><ul><ng-container *ngFor="let place of Places; let i =index"[ngSwitch]='place.cercania'><!--<li [ngStyle]="{'color': (place.stateActive) ?'blue' :'red'}"[ngClass]="{'numero_par': (i%2==0)}">--><li [ngStyle]="{'color': 'black'}"[ngClass]="{'numero_par': (i%2==0)}">{{place.nombre}}-<span *ngSwitchCase="1"[ngStyle]="{'background-color': 'green'}">Muy cerca</span><span *ngSwitchCase="2"[ngStyle]="{'background-color': 'yellow'}">Cerca</span><span *ngSwitchCase="3"[ngStyle]="{'background-color': 'red'}">Lejos</span></li></ng-container></ul>```
Porqué cuando trato de cambiar el background color con la directiva ngStyle no me funciona?
Mi código es
<ul><ng-container *ngFor="let i of listalugares"><li *ngIf="i.pacientes<10"[ngStyle]="{background-color: (i.pacientes<10)? 'aliceblue' : 'green'}"><a href="">{{i.nombre}}</a> tiene {{i.pacientes}} pacientes</li></ng-container></ul>```
[NgSwitch] es una directiva de atributo pero que para su correcto funcionamiento se ha de usar con una directiva de estructura, esta directiva estructural es *ngSwitchCase=”valueOfMatching”. El [ngSwitch] recibe como valor la variable o propiedad la cual se comparará con los casos. Mientas que el valor de *ngSwitchCase es el valor del matching, los valores de este *ngSwitchCase solo pueden ser booleanos. Ejemplo:
Realice un ejercicio similar pero con persona y estaturas.
//en el tspersonas: any =[{estatura:1.5,porte:'pequeño',edad:18,nombre:'Kevin'},{estatura:1.8,porte:'mediano',edad:15,nombre:'Lui'},{estatura:2.0,porte:'alto',edad:21,nombre:'Karla'},{estatura:1.7,porte:'mediano',edad:14,nombre:'Roman'},{estatura:2.2,porte:'alto',edad:25,nombre:'Juan'},{estatura:1.4,porte:'pequeño',edad:28,nombre:'pedro'}]
En el html
<h2>ngSwitch directiva que permite tomar varias alternativas</h2><ng-container *ngFor="let persona of personas; odd as esPar"[ngSwitch]="persona.porte"><li [ngStyle]="{color : (persona.edad>=18)? 'blue': 'red'}">{{persona.nombre}}-{{persona.edad}} años -<span *ngSwitchCase="'alto'"[ngStyle]="{color: 'green'}">alto({{persona.estatura}} mts)</span><span *ngSwitchCase="'mediano'"[ngStyle]="{color: 'black'}">mediano({{persona.estatura}} mts)</span><span *ngSwitchCase="'pequeño'"[ngStyle]="{color: 'orange'}">pequeño({{persona.estatura}} mts)</span></li></ng-container>
yo lo he usado tambien para strings y char, pero tiene que ir entre comlla simple
<ul [ngSwitch]="persona.nombre"><li *ngSwitchCase="'Miguel'">hola Miguel</li><li *ngSwitchCase="'Joshua'">hola Joshua</li><li *ngSwitchDefault>No se como te llamas :S</li></ul>
Por acá dejo mi código:
html
<div class="textcenter"><h3>{{ title }} app is running!</h3>Tu nombre es {{ name }}{{ lastName }}<br /><input
type="text" placeholder="Nombre"(keyup)="check()"[(ngModel)]="name"/><input
type="text" placeholder="Apellido"(keyup)="check()"[(ngModel)]="lastName"/><button [disabled]="notReady"(click)="hello()">Hi</button></div><br /><span class="textmarginleft">{{ coordinates }}</span><br /><div class="inline" id="map"></div><div class="inline" id="list"><ul><ng-container *ngFor="let place of places; let i = index"><li *ngIf="place.active"[ngClass]="{ evennumber: (i + 1) % 2 === 0 }">{{ place.name}}</li></ng-container></ul><ul><ng-container *ngFor="let place of places; let i = index"><li
[ngStyle]="{ 'text-decoration': place.active ? '' : 'line-through' }"[ngSwitch]="place.closeness">{{ place.name}}-<span *ngSwitchCase="1"[ngStyle]="{ 'color': place.color }">Cercano</span><span *ngSwitchCase="2"[ngStyle]="{ 'color': place.color }">Intermedio</span><span *ngSwitchCase="3"[ngStyle]="{ 'color': place.color }">Lejano</span></li></ng-container></ul></div>
ts
import{Component,OnInit}from'@angular/core';import{ environment }from'src/environments/environment';import*as mapboxglfrom"mapbox-gl";@Component({selector:'app-root',templateUrl:'./app.component.html',styleUrls:['./app.component.sass']})exportclassAppComponentimplementsOnInit{title: string ='Angular';name: string ='';lastName: string ='';notReady: boolean =true;map: mapboxgl.Map;coordinates: any;places: any =[{color:'#00ff00',closeness:1,distance:3,active:true,name:"Florería la Gardenia"},{color:'#360000',closeness:3,distance:50,active:true,name:"Donas Vida Dulce"},{color:'#00ff00',closeness:1,distance:8,active:true,name:"Veterinaria Huellitas"},{color:'#360000',closeness:3,distance:30,active:true,name:"Sushi Roll"},{color:'#baf73c',closeness:2,distance:10,active:false,name:"Hotel la Gracia"},{color:'#baf73c',closeness:2,distance:20,active:false,name:"Zapatería Clavo"},];ngOnInit():void{ mapboxgl.accessToken= environment.mapboxKey;this.map=newmapboxgl.Map({container:'map',style:'mapbox://styles/mapbox/streets-v11',center:[-74.0700526,4.6489681],zoom:10});this.createMarker(-74.0700526,4.6489681)}createMarker(lng: number,lat: number):void{const marker =newmapboxgl.Marker({draggable:true}).setLngLat([lng, lat]).addTo(this.map) marker.on('drag',()=>{this.coordinates= marker.getLngLat()})}check():void{if(this.name===''||this.lastName===''){this.notReady=true;}else{this.notReady=false;}}hello():void{alert(`Welcome to this App ${this.name}${this.lastName}`);}}