<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ GM Fuster - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ GM Fuster - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 19 May 2026 10:02:47 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/author/gemma/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ 48 respuestas a las preguntas  más populares sobre Angular en StackOverflow ]]>
                </title>
                <description>
                    <![CDATA[ He recopilado las preguntas sobre Angular más comunes en StackOverflow, con sus respuestas.  Estas preguntas fueron elegidas en base a su puntuación. Ya seas un experto o un principiante, puedes aprender de las experiencias de otros. Tabla de contenidos  * Angular — Promise vs Observable  * Diferencia entre ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/48-respuestas-a-las-preguntas-mas-populares-sobre-angular-en-stackoverflow/</link>
                <guid isPermaLink="false">62fe70fa7b4ec209a4024378</guid>
                
                    <category>
                        <![CDATA[ angular ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Mon, 17 Oct 2022 03:10:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/09/SO_FCC.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/48-answers-on-stack-overflow-to-the-most-popular-angular-questions-52f9eb430ab0/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">48 answers on StackOverflow to the most popular Angular questions</a>
      </p><p>He recopilado las preguntas sobre Angular más comunes en StackOverflow, con sus respuestas. &nbsp;Estas preguntas fueron elegidas en base a su puntuación. Ya seas un experto o un principiante, puedes aprender de las experiencias de otros.</p><!--kg-card-begin: html--><h3 id="tabladecontenidos">Tabla de contenidos</h3><!--kg-card-end: html--><ul><li><a href="#promisevsobservable">Angular — Promise vs Observable</a></li><li><a href="#constructoryngoninit">Diferencia entre Constructor y ngOnInit</a></li><li><a href="#nosepuedevincularangmodel">Error: "Can’t bind to 'ngModel' since it isn’t a known property of 'input'", No se puede vincular a 'ngModel' porque &nbsp;no es una propiedad conocida de 'input'.</a></li><li><a href="#vinculacionhtmlangular">Vinculacion de HTML en Angular</a></li><li><a href="#angularrxjs">Angular/RxJs - &nbsp;¿Cuando debo dejar de suscribir de 'Subscription'?</a></li><li>¿<a href="https://www.freecodecamp.org/news/48-answers-on-stack-overflow-to-the-most-popular-angular-questions-52f9eb430ab0/#5251" rel="noopener">C</a>ó<a href="#selecionarelementoplantillacomponente">mo puedo seleccionar un elemento en una plantilla componente?</a></li><li>¿<a href="#ngshownghideequivalentes">Cuales son los equivalentes de ngShow y ngHide en Angular?</a></li><li><a href="#empaquetarparapublicar">Como empaquetar una aplicación de Angular para producción</a></li><li><a href="#subjectvsobservable">BehaviorSubject vs Observable</a></li><li><a href="#directivevscomponent">@Directive vs @Component en Angular</a></li><li><a href="#mapisnotafunctionin">Error de Angular HTTP GET with TypeScript : &nbsp;http.get(…).map is not a function in [null] (http.get(...).map no es una función en [null])</a></li><li><a href="#angularjquery">¿Cómo se puede usar jQuery con Angular?</a></li><li><a href="#noproviderforhttp">Excepción en Angular: No provider for Http (No hay proveedor de HTTP)</a></li><li><a href="#cantbindto">Can’t bind to ‘formGroup’ since it isn’t a known property of ‘form’ (No se puede enlazar a 'formGroup' porque no es una propiedad conocida de 'form'</a></li><li><a href="#cantresolveallparameters">Error DI de Angular— EXCEPTION: Can’t resolve all parameters (Excepción: No se pueden resolver todos los parámetros)</a></li><li><a href="#headersforrequest">Angular — Establecer los headers (encabezamientos) para cada request (solicitud)</a></li><li><a href="#ngIfElse">¿Cómo se puede usar *ngIf else en Angular?</a></li><li><a href="#noproviderfornameservice">Error: Angular no provider for NameService (No hay proveedor para NombreServicio)</a></li><li><a href="#bindingelementtoobject">Vinculando el elemento seleccionado a un object en Angular</a></li><li><a href="#declarationsprovsngmodule">¿Cuál es la diferencia entre declaraciones, proveedores e importación (import) en NgModule?</a></li><li><a href="#rutaactiva">En Angular, ¿Cómo se determina la ruta activa?</a></li><li><a href="#clisass">Opciones CLI SASS de Angular</a></li><li><a href="#changedetectionmanual">Activar la detección de cambios en Angular &nbsp;manualmente </a></li><li><a href="#angulartypescript">Angular y Typescript: No se pueden encontrar los nombres.</a></li><li><a href="#moduleid">Angular — ¿Cuál es el significado de module.id en el componente?</a></li><li><a href="#getnewselection">¿Cómo se puede obtener una nueva selección en "select" en Angular 2?</a></li><li><a href="#cantbindngForIn">Excepción de Angular: Can’t bind to ‘ngForIn’ since it isn’t a known native property (No se puede vincular a 'ngForIn' porque no es una propiedad nativa conocida.</a></li><li><a href="#ngifngfor">*ngIf y *ngFor en el mismo elemento causa un error</a></li><li><a href="#swatcheq">¿Cuál es el equivalente del $watch de AngularJS en Angular?</a></li><li><a href="#importlodash">Importando lodash en angular2 + aplicaciones typescript</a></li><li><a href="#routechange">¿Cómo se detecta un cambio de ruta en Angular?</a></li><li><a href="#globalevents">Global Events en Angular (eventos globales)</a></li><li><a href="#systemjswebpack">¿Cuales son algunas diferencias entre SystemJS y Webpack?</a></li><li><a href="#cantfindpromise">Angular: Can’t find Promise, Map, Set and Iterator (No se puede encontrar Promise, Map, Set y Iterator)</a></li><li><a href="#rc4">Angular RC4 — Angular ^2.0.0 con Typescript 2.0.0</a></li><li><a href="#detectinputchanges">¿Cómo se detecta cuando cambia un valor de @Input() en Angular?</a></li><li><a href="#urlarguments">¿Cómo se pasan argumentos url (query string) a una solicitud (request) de HTTP en Angular?</a></li><li><a href="#deployangular">¿Cómo se despliegan las aplicaciones de Angular?</a></li><li><a href="#ngforwithindex">ngFor con index como un atributo con un valor</a></li><li><a href="#globalconstants">Define constantes globales en Angular 2</a></li><li><a href="#pipesservicescomponents">Angular — Usar pipes en servicios y componentes</a></li><li><a href="#cantbindrouterlink">Excepción en Angular2: Can’t bind to ‘routerLink’ since it isn’t a known native property (No se puede enlazar con 'routerLink' porque no es una propiedad &nbsp;nativa conocida.</a></li><li><a href="#dynamictabs">Angular 2 pestañas dinámicas con componentes seleccionados por el usuario por click.</a></li><li><a href="#eventemitterobservable">Delegación: EventEmitter o Observable en Angular</a></li><li><a href="#bootstrapangular">¿Cómo se añade bootstrap a un proyecto angular-cli?</a></li><li>A<a href="#accesskeyvalue">cceso a key y value de un objecto que utiliza *ngFor</a></li><li><a href="#cantbindtongfor">Excepción de Angular: Can’t bind to ‘ngFor’ since it isn’t a known native property (No se puede enlazar a 'ngFor' porque no es una propiedad nativa conocida).</a></li><li><a href="#fontawesome">¿Cómo se añade font-awesome a un proyecto Angular 2 + CLI </a></li><li><a href="#httphttpc">Diferencia entre HTTP y HTTPClient en angular 4</a></li></ul><p>¡Disfruta!</p><!--kg-card-begin: html--><h3 id="promisevsobservable">Angular - Promise vs Observable</h3><!--kg-card-end: html--><blockquote>551+ votos<em><em>? 1</em></em>50,497+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/6364715/rohit">Rohit</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>¿Alguien puede explicar la diferencia entre <code>Promise</code> y <code>Observable</code> en Angular?</p><p>Un ejemplo de cada uno sería útil para comprender los dos. ¿En qué escenario podemos utilizar cada caso?</p><blockquote><a href="https://stackoverflow.com/users/217408" rel="noopener"><strong><strong><em><em>Günter Zöchbauer</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (686+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong><strong>Promise</strong></strong></p><p>Una <code>Promise</code> se encarga de un <strong>solo evento</strong> cuando una operación asincrona (async) completa sea con éxito o error.</p><p>Nota: Hay librerias de promesas ( <code>Promise</code> ) que permiten la cancelación, pero ES6 <code>Promise</code> no lo permite.</p><p><strong><strong>Observable</strong></strong></p><p>Un <code>Observable</code> es como un <code><strong><strong>Stream</strong></strong></code> (en muchos lenguages) y permite pasar cero o más eventos donde se llama a los suscriptores para cada evento.</p><p>A menudo se prefiere un <code>Observable</code> a una &nbsp;<code>Promise</code> porque proporciona las características de <code>Promise</code> y más. Con un <code>Observable</code> no importa si se desea trabajar con 0, 1 o múltiples eventos. Se puede utilizar la misma API en cada caso.</p><p>Un <code>Observable</code> también tiene la ventaja sobre una <code>Promise</code> de que es <strong><strong>cancelable</strong></strong>. Si ya no se necesita el resultado de una solicitud HTTP a un servidor o alguna otra operación asincrónica costosa, la <code>Subscription</code> de un <code>Observable</code> permite cancelar la suscripción, mientras que una <code>Promise</code> llamará a la devolución de llamada &nbsp;(callback), exitosa o fallida, incluso si ya no se necesita.</p><p> <code>Observable</code> proporciona <strong>operadores </strong>como <code>map</code>, <code>forEach</code>, <code>reduce</code>, ... similares a los de un arreglo.</p><p>También hay operadores poderosos como <code>retry()</code>, o <code>replay()</code>, ... que suelen ser bastante útiles.</p><p><a href="https://stackoverflow.com/questions/37364973" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="constructoryngoninit">Diferencia entre Constructor y ngOnInit</h3><!--kg-card-end: html--><blockquote>444+ votos<em><em>? 1</em></em>90,166+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/4029338/haseena-p-a">Haseena P A</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Angular proporciona el gancho de ciclo de vida (lifecycle hook) <code>ngOnInit</code> por defecto.</p><p>¿Por qué usar <code>ngOnInit</code> , si ya tenemos constructor <code>constructor</code>?</p><blockquote><a href="https://stackoverflow.com/users/5043867" rel="noopener"><strong><strong><em><em>Pardeep Jain</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (512+</em></em></strong><em> votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>El <code>Constructor</code> es un método predeterminado de la clase que se ejecuta cuando se crea una instancia de la clase y garantiza la inicialización adecuada de los campos en la clase y sus subclases. &nbsp;Angular, o mejor dicho, Dependency Injector (DI o Inyector de dependencia) analiza los parámetros del constructor y cuando crea una nueva instancia al llamar a <code>new MiClase()</code> intenta encontrar proveedores que coincidan con los tipos de parámetros del constructor, los resuelve y los pasa al constructor como</p><pre><code class="language-js">new MiClase(argumentos);</code></pre><p><code>ngOnInit</code> es un enlace de ciclo de vida que Angular2 llama para indicar que Angular ha terminado de crear el componente.</p><p>Hay que importar <code>OnInit</code> para usarlo (realmente implementar <code>OnInit</code> no es obligatorio, pero se considera una buena práctica):</p><pre><code class="language-js">import {Component, OnInit} from '@angular/core';</code></pre><p>Luego para usar el método de <code>OnInit</code> tenemos que implementarlo en la clase así.</p><pre><code class="language-js">export class App implements OnInit{
  constructor(){
     //se llama la primera vez, antes de ngOnInit()
  }
  
  ngOnInit(){
     //se llama despues del constructor y despues de la primera llamada a ngOnChanges() 
  }
}</code></pre><p><code>Implementa esta interfaz para ejecutar lógica de inicialización después de que las propiedades enlazadas a datos de tu directiva (directive) hayan sido inicializadas. ngOnInit es llamado justo después de que las propiedades enlazadas a datos de la directiva &nbsp;hayan sido revisadas por primera vez, y antes de que sus hijos sean revisados. Solamente es invocado una vez cuando la directiva es instanciada.</code></p><p>La mayor parte del tiempo se usa <code>ngOnInit</code> para las declaraciones e inicializaciones y así evitar trabajar en el constructor. El constructor solamente debe usarse para inicializar miembros de la clase, pero no para hacer un "trabajo" real.</p><p>Por lo tanto, deberías usar <code>constructor()</code> para establecer Dependency Injection (inyección de dependencia) y poco más. Es mejor empezar con el código de ejecución en <code>ngOnInit()</code> &nbsp;- es donde/cuando se han resuelto los enlaces de los componentes.</p><p><a href="https://stackoverflow.com/questions/35763730" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="nosepuedevincularangmodel">Error: "Can’t bind to 'ngModel' since it isn’t a known property of 'input'"; No se puede vincular a 'ngModel' ya que no es una propiedad conocida de 'input'</h3><!--kg-card-end: html--><blockquote>442+ votos<em><em>? 2</em></em>46,901+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/3433751/anthony-breneli%C3%A8re">abreneliere</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Tengo el siguiente error al iniciar mi aplicación de Angular, incluso si el componente no se muestra.</p><p>Tengo que comentarlo para que mi aplicación funcione.</p><pre><code class="language-bash">zone.js:461 Unhandled Promise rejection: Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'. ("
    &lt;div&gt;
        &lt;label&gt;Creado:&lt;/label&gt;
        &lt;input  type="text" [ERROR -&gt;][(ngModel)]="test" placeholder="foo" /&gt;
    &lt;/div&gt;
&lt;/div&gt;"): InterventionDetails@4:28 ; Zone: &lt;root&gt; ; Task: Promise.then ; Value:</code></pre><p>Aquí esta el fichero:</p><pre><code class="language-js">import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Intervention } from '../../model/intervention';

@Component({
    selector: 'intervention-details',
    templateUrl: 'app/intervention/details/intervention.details.html',
    styleUrls: ['app/intervention/details/intervention.details.css']
})

export class InterventionDetails
{
    @Input() intervention: Intervention;
    public test : string = "toto";
}</code></pre><blockquote><a href="https://stackoverflow.com/users/3433751" rel="noopener"><strong><strong><em><em>abreneliere</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (674+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>En app.module.ts, he añadido :</p><pre><code class="language-js">import { FormsModule } from '@angular/forms';

[...]

@NgModule({
  imports: [
    [...]
    FormsModule
  ],
  [...]
})</code></pre><p><a href="https://stackoverflow.com/questions/38892771" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="vinculacionhtmlangular">Vinculación de HTML en Angular</h3><!--kg-card-end: html--><blockquote>385+ votos<em><em>? 2</em></em>27,115+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/3433751/anthony-breneli%C3%A8re">Aviad P.</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy escribiendo una aplicación en Angular, y tengo una respuesta HTML que quiero mostrar. ¿Cómo lo hago? Si uso <code>{{myVal}}</code> codifica todos los caracteres HTML .</p><p>Necesito de alguna manera vincular el html interno de un div al valor de la variable.</p><blockquote><a href="https://stackoverflow.com/users/427763" rel="noopener"><strong><strong><em><em>prolink007</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (691+</em></em></strong><em> votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>La sintaxis correcta es:</p><pre><code class="language-html">&lt;div [innerHTML]="theHtmlString"&gt;&lt;/div&gt;</code></pre><p>Funciona en <code>5.2.6</code></p><p><a href="https://stackoverflow.com/questions/31548311" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="angularrxjs">Angular/RxJs -  ¿Cuándo debo dejar de suscribir de 'Subscription'?</h3><!--kg-card-end: html--><blockquote>320+ votos<em><em>? 6</em></em>9,606+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/1429493/sergey-tihon">Sergey Tihon</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>¿Cuándo debo guardar las instancias de <code>Subscription</code> e invocar <code>unsubscribe()</code> durante el ciclo de vida de NgOnDestroy y cuándo puedo sencillamente ignorarlas?</p><p>Guardar todas las suscripciones introduce mucho desorden en el código del componente.</p><p>La guía de Angular para cliente de HTTP lo indica de esta manera:</p><pre><code class="language-js">getHeroes() {
  this.heroService.getHeroes()
                   .subscribe(
                     heroes =&gt; this.heroes = heroes,
                     error =&gt;  this.errorMessage = &lt;any&gt;error);
}</code></pre><p>Pero la de Angular de navegación dice:</p><p><code>Eventualmente, navegaremos a otro sitio. El enrutador eliminará este componente del DOM y lo destruirá. Necesitamos hacer limpieza antes de que esto suceda. En concreto, debemos eliminar la suscripción (unsubscribe) antes de que Angular destruya el componente. No hacerlo puede provocar una pérdida de memoria.</code></p><p><code>Dejamos la suscripción de nuestro Observable en ngOnDestroy.</code></p><pre><code class="language-js">private sub: any;

ngOnInit() {
  this.sub = this.route.params.subscribe(params =&gt; {
     let id = +params['id']; // (+) convierte la cadena 'id' a un numero
     this.service.getHero(id).then(hero =&gt; this.hero = hero);
   });
}

ngOnDestroy() {
  this.sub.unsubscribe();
}</code></pre><blockquote><a href="https://stackoverflow.com/users/939634" rel="noopener"><strong><strong><em><em>seangwright</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (508+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><h4 id="-editado-3-la-soluci-n-oficial-2017-04-09-"><strong>— — Editado 3 — La solución ‘oficial’ (2017/04/09)</strong></h4><p>Hablé con Ward Bell sobre esta pregunta en NGConf (incluso le mostré esta respuesta que dijo que era correcta) pero me dijo que el equipo de docs para Angular tenía una solución a esta pregunta que aún no está publicada (aunque están trabajando para que se apruebe). También me dijo que podía actualizar mi respuesta en SO con la siguiente recomendación oficial.</p><p>La solución que todos deberíamos usar en el futuro es agregar un campo <code>private ngUnsubscribe: Subject = new Subject();</code> a todos los componentes que tienen llamadas &nbsp;<code>.subscribe()</code> a <code>Observable</code>s dentro del código de la clase.</p><p>Luego llamamos <code>this.ngUnsubscribe.next(); this.ngUnsubscribe.complete();</code> en nuestro <code>ngOnDestroy()</code> .</p><p>La salsa secreta es (como ya indica <a href="https://stackoverflow.com/a/42695571/939634" rel="noopener">@metamaker</a>) llamar a <code>.takeUntil(this.ngUnsubscribe)</code> antes de nuestra llamada a &nbsp;<code>.subscribe()</code> lo que garantiza que las suscripciones se eliminen antes de que se destruya el componente.</p><p>Ejemplo:</p><pre><code class="language-js">import { Component, OnDestroy, OnInit } from '@angular/core';
import 'rxjs/add/operator/takeUntil';
// import { takeUntil } from 'rxjs/operators'; // para rxjs ^5.5.0 lettable operators
import { Subject } from 'rxjs/Subject';

import { MiServicio } from '../mi-cosa.service';

@Component({
    selector: 'mi-cosa',
    templateUrl: './mi-cosa.component.html'
})
export class MiCosaComponent implements OnDestroy, OnInit {
    private ngUnsubscribe: Subject = new Subject();
    
    constructor(
        private miServicio: MiServicio,
    ) { }
    
    ngOnInit() {
        this.miServicio.getCosas()
            .takeUntil(this.ngUnsubscribe)
            .subscribe(cosas =&gt; console.log(cosas));
            
        /* si se usan lettable operators in rxjs ^5.5.0
        this.migServicio.getCosas()
            .pipe(takeUntil(this.ngUnsubscribe))
            .subscribe(cosas =&gt; console.log(cosas));
        */
        
        this.miServicio.getOtrasCosas()
            .takeUntil(this.ngUnsubscribe)
            .subscribe(cosas =&gt; console.log(cosas));
            
    }
    
    ngOnDestroy() {
        this.ngUnsubscribe.next();
        this.ngUnsubscribe.complete();
    }
}</code></pre><h4 id="-editado-2-2016-12-28-"><strong>— — Editado 2 (2016/12/28)</strong></h4><p><strong>fuente <strong>5</strong></strong></p><p>En el tutorial de Angular, el capítulo de rutas ahora dice esto: “El enrutador ( Router) maneja los observables que proporciona y localiza las suscripciones. Las suscripciones se limpian cuando el componente es destruido, protegiendo contra pérdidas de memoria, por lo que no necesitamos cancelar la suscripción de los parámetros de ruta observables.” — <a href="https://stackoverflow.com/questions/38008334/angular2-rxjs-when-should-i-unsubscribe-from-subscription/41177163?noredirect=1#comment69909721_41177163" rel="noopener">Mark Rajcok</a></p><h4 id="-editado-1"><strong>— — Editado 1</strong></h4><p><strong>Fuente <strong>4</strong></strong></p><p>En este &nbsp;<a href="https://youtu.be/WWR9nxVx1ec?t=20m32s" rel="noopener">video de NgEurope</a> Rob Wormald dice que no necesitas eliminar la suscripción. &nbsp;También menciona el servicio &nbsp;<code>http</code> y <code>ActivatedRoute.params</code> en este <a href="https://youtu.be/VLGCCpOWFFw?t=33m37s" rel="noopener">video de Noviembre 2016</a>.</p><h4 id="-repuesta-original"><strong>— — Repuesta Original</strong></h4><p><strong><strong>TLDR:</strong></strong></p><p>Para esta pregunta hay 2 tipos de <code>Observables</code> - de valor <strong>finito </strong>y<strong> </strong>valor <strong>infinito</strong>.</p><p>Las <code>Observables</code> <code>http</code> producen valores <strong><strong>finit</strong>os</strong> (1) algo similar a un evento del DOM ( <code>event listener</code> ) produce <code>Observables</code> de valores <strong><strong>infinit</strong>os</strong>.</p><p>Si llamas de forma manual a <code>subscribe</code> (sin usar una pipe asíncrona), haz un <code>unsubscribe</code> de las <code>Observables</code> <strong><strong>infinit</strong>as</strong> .</p><p>No te preocupes por las <strong><strong>finit</strong>as</strong> , <code>RxJs</code> se encargara de ellas.</p><p><strong>Fuente<strong> 1</strong></strong></p><p>He localizado una respuesta de Rob Wormald en Angular Gitter.</p><p>Dice que (reorganizado para que esté más claro y el énfasis es mío)</p><p><code>Si es una secuencia de <strong>un solo valor</strong> (como una solicitud http (request)) la <strong>limpieza manual no es necesaria</strong> (suponiendo que te suscribes en el controller de manera manual)</code></p><p><code>Debería decir "si es <strong>una secuencia que termina</strong>" (como son las de secuencia de un solo valor, como la http)</code></p><p><code><strong>Si<strong> </strong>la secuencia es infinita</strong>, <strong>deberías elimnar la suscripción (<strong>unsubscribe</strong>)</strong> lo que se consigue usando la pipe asíncrona.</code></p><p>También comenta en este video de <a href="https://youtu.be/UHI0AzD_WfY?t=26m42s" rel="noopener">youtube</a> sobre Observables que <code>se limpian ellas mismas</code>... en el contexto de las Observables que <code>terminan</code> (como las Promesas (promeses), que siempre terminan porque siempre producen un valor y terminan - nunca nos hemos preocupado de eliminar las suscripciones de promesas para que limpien escuchadores de eventos &nbsp;<code>xhr</code> (event listeners)).</p><p><strong>Fuente <strong>2</strong></strong></p><p>También en &nbsp;la guía Rangle de Angular 2:</p><p><code>En la mayoría de los casos no necesitamos eliminar la suscripción (unsubscribe) a no ser que queramos cancelar antes de tiempo o la Observable dure más que lo que necesita nuestra suscripción. El comportamiento por defecto de los operadores de Observable es eliminar la suscripción tan pronto como los mensajes de .complete() o .error() son publicados. Ten en cuenta que RxJS fue diseñado para utilizarse en modo "dispara y olvidate" en la mayoría de los casos.</code></p><p>Qué quiere decir que <code>nuestra Observable dura más que lo que necesita nuestra suscripción?</code></p><p>Se refiere a cuando una suscripción es creada dentro de un componente que es destruido antes de que la <code>Observable</code> termine.</p><p>Entiendo esto así, si suscribimos a una solicitud (request) &nbsp;<code>http</code> o a una observable que emite 10 valores y nuestro compenente es destruido antes de que esa solicitud &nbsp;<code>http</code> vuelva o los 10 valores sean emitidos no tenemos ningún problema.</p><p>Cuando la solicitud vuelve o el décimo valor es emitido la <code>Observable</code> se completará y todos los recurdos seran liberados.</p><p><strong>Fuente <strong>3</strong></strong></p><p>El artículo original hacía referencia a un ejemplo en una página que ya no se encuentra.</p><p><a href="https://stackoverflow.com/questions/38008334" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="selecionarelementoplantillacomponente">¿Cómo puedo seleccionar un elemento en una plantilla componente?</h3><!--kg-card-end: html--><blockquote>263+ votos<em><em>? 2</em></em>65,966+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/2748475/aman-gupta">Aman Gupta</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>¿Alguién sabe como obtener un elemento definido en la plantilla (template) de un componente? Polymer lo hace muy fácil con &nbsp;<code>$</code> and <code>$$</code>.</p><p>Me pregunto como hacerlo en Angular.</p><p>En este ejemplo de un tutorial:</p><pre><code class="language-js">import {Component} from '@angular/core'

@Component({
    selector:'mostrar'
    template:`
     &lt;input #miNombre(input)="actualizarNombre(miNombre.value)"/&gt;
     &lt;p&gt;Mi nombre : {{miNombre}}&lt;/p&gt;
    `
    
})
export class MostrarComponent {
    miNombre: string = "Aman";
    actualizarNombre(input: String) {
        this.miNombre = input;
    }
}</code></pre><p>¿Cómo puedo obtener la referencia a los elementos <code>p</code> o <code>input</code> dentro de la misma clase?</p><blockquote><a href="https://stackoverflow.com/users/1413538" rel="noopener"><strong><strong><em><em>Brocco</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (149+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Puedes obtener la referencia al elemento del DOM con <code>ElementRef</code> inyectandolo en el constructor:</p><pre><code class="language-js">constructor(miElemento: ElementRef) { ... }</code></pre><p><a href="https://stackoverflow.com/questions/32693061" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="ngshownghideequivalentes">¿Cuales son los equivalentes de ngShow y ngHide en Angular?</h3><!--kg-card-end: html--><blockquote>261+ votos<em><em>? 2</em></em>06,651+ vistas<br><strong><strong><a href="https://stackoverflow.com/users/2870735/mihai-r%C4%83ducanu">Mihai Răducanu</a> </strong></strong><em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Tengo un número de elementos que quiero hacer visibles bajo ciertas condiciones.</p><p>En AngularJS haría esto:</p><pre><code class="language-html">&lt;div ng-show="miVar"&gt;alguna cosa&lt;/div&gt;</code></pre><p>¿Cómo lo hago en Angular?</p><blockquote><a href="https://stackoverflow.com/users/217408" rel="noopener"><strong><strong><em><em>Günter Zöchbauer</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (445+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Enlaza con la propiedad &nbsp;<code>hidden</code> :</p><pre><code class="language-html">[hidden]="!miVar"</code></pre><p>Ver también</p><ul><li><a href="https://developer.mozilla.org/es/docs/Web/HTML/Global_attributes/hidden">HTML: Lenguaje de etiquetas de hipertexto | MDN (mozilla.org)</a></li></ul><p><code>hidden</code> tiene algunos problemas porque puede tener conflictos con CSS para la propierdad <code>display</code>.</p><p>En este ejemplo de <a href="https://plnkr.co/edit/SO3c3UUT3LBvhNAeriCz?p=preview" rel="noopener"><strong><strong>Plunker</strong></strong></a> &nbsp;<code>some</code> &nbsp;no desaparece porque tiene un estilo (style).</p><pre><code class="language-css">:host {display: block;}</code></pre><p>(Puede que funcione de manera diferente en navegadores diferentes — Yo he usado Chrome 50)</p><p><strong>Para evitar ese problema</strong></p><p>Lo puedes solucionar añadiendo</p><pre><code class="language-css">[hidden] { display: none !important;}</code></pre><p>A un estilo (style) global en <code>index.html</code>.</p><p><strong>otro problema</strong></p><pre><code class="language-html">hidden="false"
hidden="{{false}}"
hidden="{{estaEscondido}}" // estaEscondido = false;</code></pre><p>es lo mismo que </p><pre><code class="language-html">hidden="true"</code></pre><p>y no mostrata el elemento.</p><p><code>hidden="false"</code> asigna la cadena <code>"false"</code> lo que se considera true (porque no es una cadena vacía).<br>Solamente el valor &nbsp;<code>false</code> o quitar el atributo hará que se muestre el elemento.</p><p>Usar <code>{{}}</code> también convierte la expression a una cadena y no funcionará como esperamos.</p><p>Solamente usando &nbsp;<code>[]</code> funciona como esperamos porque este <code>false</code> es asignado &nbsp;<code>false</code> en lugar de &nbsp;<code>"false"</code>.</p><p><code><strong><strong>*ngIf</strong></strong></code><strong><strong> vs <code>[hidden]</code></strong></strong></p><p><code>*ngIf</code> quita el contenido del DOM mientras que <code>[hidden]</code> cambia la propiedad <code>display</code> para que no se muestre el contenido, pero el contenido sigue en el DOM.</p><p><a href="https://stackoverflow.com/questions/35578083" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="empaquetarparapublicar">Como empaquetar una aplicación de Angular para producción</h3><!--kg-card-end: html--><blockquote>258+ votos<em><em>? 1</em></em>11,603+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/4155124/pat-m">Pat M</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Me gustaría conocer la mejor forma y la más actual (y espero que la más sencilla) &nbsp;para empaquetar Angular (version 2, 4, …) para producción en un servidor en activo.</p><p>Por favor, incluid la versión de Angular en las respuestas para que pueda saber que hacer dependiendo de las versiones.</p><blockquote><a href="https://stackoverflow.com/users/1630604" rel="noopener"><strong><strong><em><em>Nicolas Henneaux</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (267+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><h4 id="2-x-4-x-5-x-typescript-con-angular-cli"><strong><code>2.x, 4.x, 5.x</code> (TypeScript) con Angular CLI</strong></h4><h4 id="configurar-una-vez"><strong>Configurar una vez</strong></h4><ul><li><code>npm install -g @angular/cli</code></li><li><code>ng new ficheroDelProyecto</code> crea una aplicación nueva.</li></ul><h4 id="configuran-el-empaquetado"><strong>Configuran el empaquetado</strong></h4><ul><li><code>ng build --prod</code> (en la línea de comando en el directorio <code>ficheroDelProyecto</code>)</li><li><em>marca <em><code>prod</code> </em>para empaquetado para producción<em> (</em>ver la documentación para las opciones de <em><code>prod</code>).</em></em></li><li>Comprime los recursos con <a href="https://es.wikipedia.org/wiki/Brotli">Brotli </a> con el siguiente commando <code>for i in dist/*; do brotli $i; done</code></li></ul><p><em>lo paquetes se generan por defecto en <strong>ficheroDelProyecto</strong><em><strong><strong>/dist/</strong></strong></em></em></p><h4 id="output"><strong>Output</strong></h4><p><em>Tamaños con <em>Angular <code>5.2.8</code> </em>con<em> CLI <code>1.7.2</code></em></em></p><ul><li><code>dist/main.[hash].bundle.js</code> El paquete de tu aplicación [ tamaño: 151 KB para una nueva vacía de CLI , <strong><strong>36 KB</strong></strong> comprimida].</li><li><code>dist/polyfill.[hash].bundle.js</code> con dependencias (@angular, RxJS...) [tamaño: 58 KB para una nueva de Angular CLI vacía, <strong><strong>17 KB</strong></strong> comprimida].</li><li><code>dist/index.html</code> punto de entrada de la aplicación.</li><li><code>dist/inline.[hash].bundle.js</code> webpack loader (cargador).</li><li><code>dist/style.[hash].bundle.css</code> definiciones de estilo (style).</li><li><code>dist/assets</code> recursos copiados de los de Angular CLI según la configuración.</li></ul><h4 id="despliegue-deployment-"><strong>Despliegue (deployment)</strong></h4><p>Puedes ver un avance de tu aplicación con <code>ng serve --prod</code> en tu servidor para local HTTP y así la aplicación con los ficheros para producción es accesible desde <a href="http://localhost:4200/" rel="noopener">http://localhost:4200</a>.</p><p>Para la verdadera producción, tienes que desplegar los ficheros del directorio &nbsp;<code>dist</code> en el servidor &nbsp;HTTP de tu elección.</p><p><a href="https://stackoverflow.com/questions/37631098" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="subjectvsobservable">BehaviorSubject vs Observable</h3><!--kg-card-end: html--><blockquote>250+ votos<em><em>? 1</em></em>22,248+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/6620551/kevin-mark">Kevin Mark</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy informandome sobre patrones en Angular RxJs y no entiendo la diferencia entre BehaviorSubject y un Observable.</p><p>Según lo veo yo, un BehaviorSubject es un valor que puede cambiar en el tiempo (uno se puede suscribir a ese valor y los suscriptores reciben el valor actualizado). Esto parece que es precisamente lo que es un Observable.</p><p>¿Cuándo usarías un Observable o un BehaviorSubject? ¿Cuál ofrece más ventajas si es que uno ofrece más que el otro?</p><blockquote><a href="https://stackoverflow.com/users/3070452" rel="noopener"><strong><strong><em><em>Shantanu Bhadoria</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (425+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>BehaviorSubject es un tipo de sujeto (subject), un subject es un tipo de observable así que te puedes suscribir a él como a cualquier otro observable. Lo que hace único a BehaviorSubject es:</p><ul><li>Necesita un valor inicial ya que siempre debe devolver un valor incluso si no ha recibido un <code>next()</code></li><li>Cuando encuentra una suscripción, le devuelve el último valor del sujeto (subject). &nbsp;Un observable común en Angular solo dispara cuando recibe un &nbsp;<code>onnext</code></li><li>En cualquier momento se puede sacar el valor mas reciente del sujeto (subject) en código no observable usando el método <code>getValue()</code>.</li></ul><p>Las características únicas de un sujeto (subject) en comparación con un observable son:</p><ul><li>Es un observador (observer) además de un observable, por lo tanto, puedes mandar valores a un subject ademas de suscribirte a él.</li></ul><p>Además, puedes obtener un observable de behaviorSubject utilizando &nbsp;el método <code>asobservable()</code> de BehaviorSubject.</p><p>Un Observable es un genérico, y BehaviorSubject técnicamente es un subtipo de Observable porque BehaviorSubject es un Observable con unas características particulares.</p><p>Ejemplo con BehaviorSubject:</p><pre><code class="language-js">// Behavior Subject

// a es un valor inicial. Si hay una suscripcion
// despues de esto, le llega "a" inmediatamente
let bSubject = new BehaviorSubject("a"); 

bSubject.next("b");

bSubject.subscribe((value) =&gt; {
  console.log("Suscripcion recibe", value); // suscripcion recibe b, 
                                          // esto no pasaria 
                                          // en un observable generico
                                          // o un subject generico por defecto
});

bSubject.next("c"); // suscripcion recibe c
bSubject.next("d"); // Suscipcion recibe d</code></pre><p>Ejemplo 2 con un sujeto común:</p><pre><code class="language-js">// Sujecto comun

let subject = new Subject(); 

subject.next("b");

subject.subscribe((value) =&gt; {
  console.log("suscripcion recibe", value); // suscripcion no recibe nada                                                 // en este punto
});

subject.next("c"); // suscripcion recibe c
subject.next("d"); // suscripcion recibe d</code></pre><p>Un observable puede crearse con Subject o BehaviorSubject usando <code>subject.asobservable()</code>. &nbsp;La diferencia es que no se pueden mandar valores a un observable usando &nbsp;<code>next()</code> .</p><p>En servicios en Angular, yo usaría BehaviorSubject para un servidor de datos ya que estos servicios a menudo se inicializan antes del componente y BehaviorSubject &nbsp;te asegura que el componente que consuma este servicio recibe el valor mas reciente de los datos incluso si no hay cambios desde que se creo la suscripcion a estos datos.</p><p><a href="https://stackoverflow.com/questions/39494058" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="directivevscomponent">@Directive vs @Component en Angular</h3><!--kg-card-end: html--><blockquote>239+ votos<em><em>? 6</em></em>1,582+ vistas<br><em><em><a href="https://stackoverflow.com/users/4917853/prasanjit-dey"><strong><strong>Prasanjit Dey</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>¿Cuál es la diferencia entre <code>@Component</code> y <code>@Directive</code> en Angular? Parece que ambas tienen los mismos atributos y hacen lo mismo.</p><p>¿Cuáles son los escenarios donde usar cada uno y cuándo es preferible uno sobre otro?</p><blockquote><a href="https://stackoverflow.com/users/1771017" rel="noopener"><strong><strong><em><em>jaker</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (327+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong>Un<strong> @Component requi</strong>e<strong>re </strong>una<strong> view</strong> (página donde mostrarlo)<strong> </strong>pero<strong> </strong>un<strong> @Directive </strong>no<strong>.</strong></strong></p><h3 id="directives"><strong>Directives</strong></h3><p>Un @Directive de Angular es parecido a uno de de Angular 1.0 con la opción <code>restrict: 'A'</code> (Los directives no están limitados a usarse solamente como atributos). Los directives añaden comportamiento a un elemento del DOM que ya existe, &nbsp;o a una instancia de un componente que ya existe. Un ejemplo de cuando usar un directive sería para guardar cuando un elemento recibe un click.</p><pre><code class="language-js">import {Directive} from '@angular/core';

@Directive({
    selector: "[guardaEnClick]",
    hostListeners: {
        'click': 'onClick()',
    },
})

class GuardaEnClick {
    constructor() {}
    onClick() { console.log('El elemento ha recibido un click !'); }
}</code></pre><p>Y se usaría así:</p><pre><code class="language-js">&lt;button guardaEnClick&gt;Yo guardo cuando recibo un click!&lt;;/button&gt;</code></pre><h3 id="components"><strong>Components</strong></h3><p>Un component (componente), en lugar de añadir/modificar un comportamiento, crea su propia view (página , jerarquía de los elementos del DOM) con su comportamiento adjunto. Un ejemplo de un component para una tarjeta de visita:</p><pre><code class="language-js">import {Component, View} from '@angular/core';

@Component({
  selector: 'tarjeta-visita',
  template: `
    &lt;div&gt;
      &lt;h1&gt;{{nombre}}&lt;/h1&gt;
      &lt;p&gt;{{ciudad}}&lt;/p&gt;
    &lt;/div&gt;
  `
})
class TarjetaVisita {
  @Input() nombre: string
  @Input() ciudad: string
  constructor() {}
}</code></pre><p>Y se usaría así:</p><pre><code class="language-js">&lt;tarjeta-visita [nombre]="'foo'" [ciudad]="'bar'"&gt;&lt;/tarjeta-visita&gt;</code></pre><p><code>TarjetaVisita</code> es un componente UI que se puede reusar en cualquier sitio de nuestra aplicación, incluso dentro de otros componentes. Estos componentes son lo que básicamente constituye la UI (user interface, interfaz de usuario) de nuestra aplicación.</p><h3 id="en-resumen"><strong>En resumen</strong></h3><p>Usa un component cuando quieras un conjunto de elementos del DOM que quieras reusar, y que tengan un comportamiento particular a ese componente. Usa un directive cuando quieras tener un comportamiento reusable que suplemente el comportamiento de elementos del DOM.</p><p><a href="https://stackoverflow.com/questions/32680244" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="mapisnotafunctionin">Error de Angular HTTP GET en TypeScript :  http.get(…).map is not a function in [null] (http.get(...).map no es una función en [null])</h3><!--kg-card-end: html--><blockquote>233+ votos<em><em>? 1</em></em>41,917+ vistas<br><em><em><a href="https://stackoverflow.com/users/4834129/claudiu"><strong><strong>Claudiu</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Tengo un problema con HTTP en Angular.</p><p>Quiero conseguir con <code>GET</code> una lista en <code>JSON</code> y mostrarla en la página.</p><h4 id="clase-en-el-servicio">Clase en el servicio</h4><pre><code class="language-js">import {Injectable} from "angular2/core";
import {Hall} from "./hall";
import {Http} from "angular2/http";
@Injectable()
export class HallService {
    public http:Http;
    public static PATH:string = 'app/backend/' 
    
    constructor(http:Http) {
        this.http=http;
    }
    
    getObtenerHalls() {
           return this.http.get(HallService.PATH + 'hall.json').map((res:Response) =&gt; res.json());
    }
}</code></pre><p>Y en &nbsp;<code>HallListComponent</code> llamo al método <code>getObtenerHalls</code> del servicio:</p><pre><code class="language-js">export class HallListComponent implements OnInit {
    public halls:Hall[];
    public _Id:number;
    
    constructor(private _router:Router,
                private _routeParams:RouteParams,
                private _servicio:HallService) {
        this._Id = +_routeParams.get('id');
    }
    
    ngOnInit() {
        this._servicio.getObtenerHalls().subscribe((halls:Hall[])=&gt;{ 
            this.halls=halls;
        });
    }
}</code></pre><p>Pero me da una excepción:</p><p><code>TypeError: this.http.get(...).map is not a function in [null]</code></p><h4 id="hall-center-component"><strong>hall-center.component</strong></h4><pre><code class="language-js">import {Component} from "angular2/core";
import {RouterOutlet} from "angular2/router";
import {HallService} from "./hall.service";
import {RouteConfig} from "angular2/router";
import {HallListComponent} from "./hall-list.component";
import {HallDetailComponent} from "./hall-detail.component";
@Component({
    template:`
        &lt;h2&gt;mi app&lt;/h2&gt;
        &lt;router-outlet&gt;&lt;/router-outlet&gt;
    `,
    directives: [RouterOutlet],
    providers: [HallService]
})

@RouteConfig([
    {path: '/',         name: 'HallCenter', component:HallListComponent, useAsDefault:true},
    {path: '/hall-list', name: 'HallList', component:HallListComponent}
])

export class HallCenterComponent{}</code></pre><h4 id="app-component"><strong>app.component</strong></h4><pre><code class="language-js">import {Component} from 'angular2/core';
import {ROUTER_DIRECTIVES} from "angular2/router";
import {RouteConfig} from "angular2/router";
import {HallCenterComponent} from "./hall/hall-center.component";
@Component({
    selector: 'mi-app',
    template: `
        &lt;h1&gt;Factoria&lt;/h1&gt;
        &lt;a [routerLink]="['HallCenter']"&gt;Hall - Vista General&lt;/a&gt;
        &lt;router-outlet&gt;&lt;/router-outlet&gt;
    `,
    directives: [ROUTER_DIRECTIVES]
})

@RouteConfig([
    {path: '/hall-center/...', name:'HallCenter',component:HallCenterComponent,useAsDefault:true}
])
export class AppComponent { }</code></pre><h4 id="tsconfig-json"><strong>tsconfig.json</strong></h4><pre><code class="language-json">{
  "compilerOptions": {
    "target": "ES5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules"
  ]
}</code></pre><blockquote><a href="https://stackoverflow.com/users/1873365" rel="noopener"><strong><strong><em><em>Thierry Templier</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (416+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Creo que tienes que importar esto:</p><pre><code class="language-js">import 'rxjs/add/operator/map'</code></pre><p>O en general, si quieres usar mas métodos de observables, puedes importar: </p><pre><code class="language-js">import 'rxjs/Rx';</code></pre><p><strong>ADVERTENCIA:<strong> </strong>Esto importa todos los más de<strong> 50 opera</strong>dores<strong> </strong>y los añade a la aplicación lo que afecta el tamaño y el tiempo de carga.</strong></p><p><a href="https://stackoverflow.com/questions/34515173" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="angularjquery">¿Cómo se puede usar jQuery con Angular?</h3><!--kg-card-end: html--><blockquote>233+ votos<em><em>? 2</em></em>46,869+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/2398523/waog">Waog </a></strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>¿Alguien puede decirme cómo usar <strong>jQuery </strong>con <strong>Angular</strong>?</p><pre><code class="language-js">class MiComponent {
    constructor() {
        // como acceder a los elementos del DOM desde aqui
    }
}</code></pre><p>Sé que existen soluciones alternativas, como manipular la clase o el id &nbsp;del elemento del DOM , pero me gustaría una manera más limpia de hacerlo.</p><blockquote><a href="https://stackoverflow.com/users/2881743" rel="noopener"><strong><strong><em><em>werenskjold</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (258+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>JQuery en Angular2 es pan comido comparado com ng1. Si estás usando TypeScript podrías referenciar el paquete de jQuery de typescript (o también de sus definiciones).</p><pre><code class="language-bash">tsd install jquery --save
o
typings install dt~jquery --global --save</code></pre><p>El de las definiciones no te hace falta ya que también podrías usar &nbsp;<code>any</code> como &nbsp;<code>$</code> or <code>jQuery</code></p><p>En tu componente de Angular puedes acceder a un elemento del DOM con <code>@ViewChild()</code> Una vez que la vista (view) se haya inicializado puedes usar la propiedad <code>nativeElement</code> del objecto y pasarla a jQuery.</p><p>Declarando <code>$</code> (o <code>jQuery</code>) como JQueryStatic te da una referencia a jQuery con tipo.</p><pre><code class="language-ts">import {bootstrap}    from '@angular/platform-browser-dynamic';
import {Component, ViewChild, ElementRef, AfterViewInit} from '@angular/core';
declare var $:JQueryStatic;

@Component({
    selector: 'ng-escogido',
    template: `&lt;select #selecElemento&gt;
        &lt;option *ngFor="#elemento of elementos" [value]="elemento" [selected]="elemento === valorSeleccionado"&gt;{{elemento}} opcion&lt;/option&gt;
        &lt;/select&gt;
        &lt;h4&gt; {{valorSeleccionado}}&lt;/h4&gt;`
})
export class NgEscogidoComponent implements AfterViewInit {
    @ViewChild('selecElemento') el:ElementRef;
    elementos = ['Primero', 'Segundo', 'Tercero'];
    valorSeleccionado = 'Segundo';
    
    ngAfterViewInit() {
        $(this.el.nativeElement)
            .chosen()
            .on('change', (e, args) =&gt; {
                this.valorSeleccionado = args.selected;
            });
    }
}

bootstrap(NgEscogidoComponent);</code></pre><p>Puedes verlo en plunker: <a href="http://plnkr.co/edit/Nq9LnK?p=preview" rel="noopener">http://plnkr.co/edit/Nq9LnK?p=preview</a></p><p>tslint te dirá que <code>chosen</code> no es una propiedad en $. &nbsp;Para corregirlo puedes añadir una definición a la interfaz de JQuery en tu fichero *.d.ts </p><pre><code class="language-js">interface JQuery {
    chosen(options?:any):JQuery;
}</code></pre><p><a href="https://stackoverflow.com/questions/30623825" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="noproviderforhttp">Excepción en Angular: No provider for Http (No hay proveedor de HTTP)</h3><!--kg-card-end: html--><blockquote>230+ votos <em><em>? 1</em></em>42,976+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/516389/daniel">daniel</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Me sale esto <code>EXCEPTION: No provider for Http!</code> en mi aplicación de Angular. ¿Qué estoy haciendo mal?</p><pre><code class="language-ts">import {Http, Headers} from 'angular2/http';
import {Injectable} from 'angular2/core'

@Component({
    selector: 'greetings-ac-app2',
    providers: [],
    templateUrl: 'app/greetings-ac2.html',
    directives: [NgFor, NgModel, NgIf, FORM_DIRECTIVES],
    pipes: []
})
export class GreetingsAcApp2 {
    private str:any;
    
    constructor(http: Http) {
    
        this.str = {str:'test'};
        http.post('http://localhost:18937/cuenta/registrausuario/',
            JSON.stringify(this.str),
            {
                headers: new Headers({
                    'Content-Type': 'application/json'
                })
            });</code></pre><blockquote><a href="https://stackoverflow.com/users/2083492" rel="noopener"><strong><strong><em><em>Philip Miglinci</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (381+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Importa HttpModule</p><pre><code class="language-ts">import { HttpModule } from '@angular/http';

@NgModule({
    imports: [ BrowserModule, HttpModule ],
    providers: [],
    declarations: [ AppComponent ],
    bootstrap: [ AppComponent ]
})
export default class AppModule { }

platformBrowserDynamic().bootstrapModule(AppModule);</code></pre><p>Es mejor separar el código en dos ficheros diferentes. </p><p><a href="https://stackoverflow.com/questions/33721276" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="cantbindto">Can’t bind to ‘formGroup’ since it isn’t a known property of ‘form’ (No se puede enlazar a 'formGroup' porque no es una propiedad conocida de 'form')</h3><!--kg-card-end: html--><blockquote>227+ votos<em><em>? 1</em></em>27,130+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/2433664/francescomussi">johnnyfittizio</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p><strong>EL PROBLEMA<strong>:</strong></strong></p><p>¡por favor! Estoy intentando construir una aplicación de Angular2 muy sencilla pero no funciona.</p><p><strong><strong>VERSION</strong> DE ANGULAR<strong>:</strong></strong></p><p>Angular 2.0.0 Rc5</p><p><strong>EL <strong>ERROR:</strong></strong></p><pre><code>Can't bind to 'formGroup' since it isn't a known property of 'form'</code></pre><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/SP8f73A8L3lPs6fS9frNubiN5UEniPY2yj3p" class="kg-image" alt="SP8f73A8L3lPs6fS9frNubiN5UEniPY2yj3p" width="800" height="248" loading="lazy"></figure><p><strong>EL CÓDIGO<strong>:</strong></strong></p><p>La vista:</p><pre><code class="language-html">&lt;form [formGroup]="nuevaTareaForm" (submit)="crearNuevaTarea()"&gt;
    &lt;div class="form-group"&gt;
        &lt;label for="nombre"&gt;Nombre&lt;/label&gt;
        &lt;input type="text" name="nombre" required&gt;
    &lt;/div&gt;
     &lt;button type="submit" class="btn btn-default"&gt;Enviar&lt;/button&gt;
&lt;/form&gt;</code></pre><p>El controller - componente:</p><pre><code class="language-ts">import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder }  from '@angular/forms';
import {FormsModule,ReactiveFormsModule} from '@angular/forms';
import { Tarea } from './tarea';

@Component({
    selector: 'tarea-anadir',
    templateUrl: 'app/tarea-anadir.component.html'
    
})

export class TareaAnadirComponent {

    nuevaTareaForm: FormGroup;
    
    constructor(fb: FormBuilder) 
    {
        this.nuevaTareaForm = fb.group({
            nombre: ["", Validators.required]
        });
    }
    
    anadirNuevaTarea()
    {
        console.log(this.nuevaTareaForm.value)
    }
    
}</code></pre><p>The ngModule:</p><pre><code class="language-ts">import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';

import { routing }        from './app.routing';
import { AppComponent }  from './app.component';
import { TareaServicio } from './tarea.servicio'

@NgModule({
    imports: [ 
        BrowserModule,
        routing,
        FormsModule
    ],
    declarations: [ AppComponent ],
    providers: [
        TareaServicio
    ],
    bootstrap: [ AppComponent ]
})

export class AppModule { }</code></pre><p><strong>LA PREGUNTA<strong>:</strong></strong></p><p>¿Por qué me sale ese error?</p><p></p><blockquote><a href="https://stackoverflow.com/users/6677986" rel="noopener"><strong><strong><em><em>Stefan Svrkota</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (465+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong><strong>RC5 </strong>- SOLUCIÓN</strong></p><p>Necesitas importar <code>import { REACTIVE_FORM_DIRECTIVES } from '@angular/forms'</code> en tu controller y añadirlo a tus <code>directives</code> en <code>@Component</code>. </p><p>Cuando tengas eso solucionado, puede que te de otro error porque no has añadido <code>formControlName="nombre"</code> .</p><p><strong><strong>RC6/RC7/</strong>VERSIÓN FINAL<strong> </strong>- SOLUCIÓN</strong></p><p>Tienes que importar <code>ReactiveFormsModule</code> de<code>@angular/forms</code> en tu módulo. Aquí tienes el ejemplo importando <code>ReactiveFormsModule</code> :</p><pre><code class="language-ts">import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppComponent }  from './app.component';

@NgModule({
    imports: [
        BrowserModule,
        FormsModule,
        ReactiveFormsModule
    ],
    declarations: [
        AppComponent
    ],
    bootstrap: [AppComponent]
})

export class AppModule { }</code></pre><p>Para clarificar, <code>formGroup</code> es un selector para una directive llamada <code>FormGroupDirective</code> que es parte de <code>ReactiveFormsModule</code>, por eso hay que importarlo. Se usa para enlazar un <code>FormGroup</code> existente a un elemento del DOM. </p><p><a href="https://stackoverflow.com/questions/39152071" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="cantresolveallparameters">Error DI de Angular— EXCEPTION: Can’t resolve all parameters (Excepción: No se pueden resolver todos los parámetros)</h3><!--kg-card-end: html--><blockquote>221+ votos <em><em>? 1</em></em>42,497+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/4321757/keith-otto">Keith Otto</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>He construido una aplicación básica en Angular, pero tengo un problema extraño. No puedo inyectar un servicio en uno de mis componentes. Funciona en cualquiera de los otros tres componentes que tengo.</p><p>El servicio es este:</p><pre><code class="language-ts">import { Injectable } from '@angular/core';

@Injectable()
export class MovilService {
  pantallaAncho: number;
  pantallaAlto: number;
  
  constructor() {
    this.pantallaAncho = window.outerWidth;
    this.pantallaAlto = window.outerHeight;
    
    window.addEventListener("resize", this.onWindowResize.bind(this) )
  }
  
  onWindowResize(ev: Event) {
    var win = (ev.currentTarget as Window);
    this.pantallaAncho = win.outerWidth;
    this.pantallaAlto = win.outerHeight;
  }
  
}</code></pre><p>Y el componente en el que no funciona es:</p><pre><code class="language-ts">import { Component, } from '@angular/core';
import { NgClass } from '@angular/common';
import { ROUTER_DIRECTIVES } from '@angular/router';

import {MovilService} from '../';

@Component({
  moduleId: module.id,
  selector: 'pm-header',
  templateUrl: 'header.component.html',
  styleUrls: ['header.component.css'],
  directives: [ROUTER_DIRECTIVES, NgClass],
})
export class HeaderComponent {
  movilNav: boolean = false;
  
  constructor(public ms: MovilService) {
    console.log(ms);
  }
  
}</code></pre><p>El error que me da es este:</p><p><code>EXCEPTION: Can't resolve all parameters for HeaderComponent: (?).</code></p><p>Tengo al servicio en la función de bootstrap así que tiene un provider. Y lo puedo inyectar en los constructores de los otros componentes que tengo.</p><blockquote><a href="https://stackoverflow.com/users/217408" rel="noopener"><strong><strong><em><em>Günter Zöchbauer</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (272+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Importalo directamente en el archivo en que es declarado.</p><p>No sé exactamente la causa del problema, pero lo he visto mencionado varias veces (probablemente algún tipo de dependencia circular).</p><p>También se podría arreglar cambiando el orden de los exports (no sé los detalles pero también lo he visto mencionado antes)</p><p><a href="https://stackoverflow.com/questions/37997824" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="headersforrequest">Angular — Establecer los headers (encabezamientos) para cada request (solicitud)</h3><!--kg-card-end: html--><blockquote>209+ votos<em><em>? 2</em></em>05,557+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/4135178/avijit-gupta">Avijit Gupta</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Necesito establecer headers de autorización (Authorization) una vez que el usuario haya iniciado la sesión, para cada solicitud posterior.</p><p>Para establecer los headers para una solicitud (request) particular,</p><pre><code class="language-ts">import {Headers} from 'angular2/http';
var headers = new Headers();
headers.append(headerName, value);

// HTTP POST con estos headers
this.http.post(url, data, {
  headers: headers
})
// Hacer algo con la respuesta</code></pre><p>Pero no sería factible configurar manualmente para cada solicitud.</p><p>¿Cómo configuro los encabezados (headers) solamente una vez cuando el usuario inicia la sesión y también cómo los elimino al cerrar la sesión?</p><blockquote><a href="https://stackoverflow.com/users/1873365" rel="noopener"><strong><strong><em><em>Thierry Templier</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (283+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Podrías tener un servicio que envuelva el objecto <code>Http</code> original de Angular. Algo como esto:</p><pre><code class="language-ts">import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';

@Injectable()
export class HttpClient {

  constructor(private http: Http) {}
  
  crearAutorizacionHeader(headers: Headers) {
    headers.append('Authorization', 'Basic ' +
      btoa('username:password')); 
  }
  
  get(url) {
    let headers = new Headers();
    this.crearAutorizacionHeader(headers);
    return this.http.get(url, {
      headers: headers
    });
  }
  
  post(url, data) {
    let headers = new Headers();
    this.crearAutorizacionHeader(headers);
    return this.http.post(url, data, {
      headers: headers
    });
  }
}</code></pre><p>Y en vez de inyectar el objecto <code>Http</code> inyecta (<code>HttpClient</code>).</p><pre><code class="language-ts">import { HttpClient } from './http-client';

export class MiComponent {
  // inyectamos "nuestro" HttpClient, lo llamo Http por simplificar
  constructor(http: HttpClient) {
    this.http = httpClient;
  }
  
  hacerAlgo() {
    this.http.post(url, data).subscribe(result =&gt; {
        // console.log( result );
    });
  }
}</code></pre><p>También creo que se podría hacer algo usando múltiples proveedores de la clase <code>Http</code> con tu propia clase que extienda la clase <code>Http</code> .</p><p><a href="https://stackoverflow.com/questions/34464108" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="ngIfElse">¿Cómo se puede usar *ngIf else en Angular?</h3><!--kg-card-end: html--><blockquote>205+ votos<em><em>? 2</em></em>03,768+ vistas<br><em><em><a href="https://stackoverflow.com/users/5486494/kawli-norman"><strong><strong>kawli norman</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Quiero usar <code>*ngIf else</code> (disponible desde la versión 4) en este ejemplo:</p><pre><code>&lt;div *ngIf="isValid"&gt;
  contenido ...
&lt;/div&gt;

&lt;div *ngIf="!isValid"&gt;
 otro contenido...
&lt;/div&gt;</code></pre><p>¿Cómo puedo hacer lo mismo con &nbsp;<code>ngIf else</code> ?</p><blockquote><a href="https://stackoverflow.com/users/7273246" rel="noopener"><strong><strong><em><em>Bougarfaoui El houcine</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (384+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong><strong>Angular 4 </strong>y <strong>5</strong></strong>:</p><p>Usando <code>else</code> :</p><pre><code class="language-html">&lt;div *ngIf="isValid;else otro_contenido"&gt;
    contenido ...
&lt;/div&gt;

&lt;ng-template #otro_contenido&gt;otro contenido...&lt;/ng-template&gt;</code></pre><p>También puedes usar <code>then else</code> :</p><pre><code class="language-html">&lt;div *ngIf="isValid;then contenido else otro_contenido"&gt;esto se ignora&lt;/div&gt;

&lt;ng-template #contentenido&gt;contenido...&lt;/ng-template&gt;
&lt;ng-template #otro_contenido&gt;otro contenido...&lt;/ng-template&gt;</code></pre><p>o <code>then</code> &nbsp;:</p><pre><code class="language-html">&lt;div *ngIf="isValid;then contenido"&gt;&lt;/div&gt;

&lt;ng-template #contenido&gt;contenido...&lt;/ng-template&gt;</code></pre><p><strong><strong>Demo :</strong></strong></p><p><a href="https://plnkr.co/edit/XD5vLvmwTApcaHJ66Is1" rel="noopener"><strong><strong>Plunker</strong></strong></a></p><p><strong>Detalles<strong>:</strong></strong></p><p><code>&lt;ng-template&gt;</code> : Es la implementación de Angular de la etiqueta <code>&lt;template&gt;</code> que de acuerdo a<a href="https://developer.mozilla.org/es/docs/Web/HTML/Element/template"> MDN</a> :</p><p><code>El elemento HTML &lt;template&gt; es un mecanismo para mantener el contenido HTML del lado del cliente que no se renderiza cuando se carga una página, pero que posteriormente puede ser instanciado durante el tiempo de ejecución empleando JavaScript. </code></p><p><a href="https://stackoverflow.com/questions/43006550" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="noproviderfornameservice">Error: Angular no provider for NameService (No hay proveedor para NombreServicio)</h3><!--kg-card-end: html--><blockquote>196+ votos<em><em>? 1</em></em>86,526+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/2667885/m-svrcek">M.Svrcek</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Tengo un problema cargando una clase en un componente de Angular. He intentado solucionarlo durante mucho tiempo incluso poniéndolo en un solo fichero. &nbsp;Tengo esto.</p><p><strong><strong>Application.ts</strong></strong></p><pre><code class="language-ts">/// &lt;reference path="../typings/angular2/angular2.d.ts" /&gt;

import {Component,View,bootstrap,NgFor} from "angular2/angular2";
import {NombreService} from "./services/NombreService";

@Component({
    selector:'mi-app',
    injectables: [NombreService]
})
@View({
    template:'&lt;h1&gt;Hola {{nombre}}&lt;/h1&gt;' +
    '&lt;p&gt;Amigos&lt;/p&gt;' +
    '&lt;ul&gt;' +
    '   &lt;li *ng-for="#nombre of nombres"&gt;{{nombre}}&lt;/li&gt;' +
    '&lt;/ul&gt;',
    directives:[NgFor]
})

class MiAppComponent
{
    nombre:string;
    nombres:Array&lt;string&gt;;
    
    constructor(nombreService:NombreService)
    {
        this.nombre = 'Michal';
        this.nombres = nombreService.getObtenNombres();
    }
}
bootstrap(MiAppComponent);</code></pre><p><strong><strong>services/N</strong>ombre<strong>Service.ts</strong></strong></p><pre><code class="language-ts">export class NombreService {
    nombres: Array&lt;string&gt;;
    constructor() {
        this.nombres = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
    }
    getObtenNombres()
    {
        return this.nombres;
    }
}</code></pre><p>Me da el error “No provider for NombreService” …</p><p>¿Puede alguien ayudarme?</p><blockquote><a href="https://stackoverflow.com/users/46194" rel="noopener"><strong><strong><em><em>Klas Mellbourn</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (309+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Tienes que usar <code>providers</code> en lugar de <code>injectables</code></p><pre><code class="language-ts">@Component({
    selector: 'mi-app',
    providers: [NombreService]
})</code></pre><p><a href="https://stackoverflow.com/questions/30580083" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="bindingelementtoobject">Vinculando el elemento seleccionado a un object en Angular</h3><!--kg-card-end: html--><blockquote>194+ votos<em><em>? 1</em></em>97,048+ vistas<br><em><em><a href="https://stackoverflow.com/users/372296/rharris"><strong><strong>RHarris</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Soy nuevo en Angular y estoy intentando familiarizarme con las novedades.</p><p>Me gustaría vincular un elemento seleccionado a una lista de objectos:</p><pre><code class="language-ts">@Component({
   selector: 'miApp',
   template: `&lt;h1&gt;Mi Aplicacion&lt;/h1&gt;
              &lt;select [(ngModel)]="valorSeleccionado"&gt;
                 &lt;option *ngFor="#p de paises" value="p.id"&gt;{{c.nombre}}&lt;/option&gt;
              &lt;/select&gt;`
})
export class AppComponent{
    paises = [
       {id: 1, nombre: "United States"},
       {id: 2, nombre: "Australia"}
       {id: 3, nombre: "Canada"}
       {id: 4, nombre: "Brazil"}
       {id: 5, nombre: "England"}
     ];
    valorSeleccionado = null;
}</code></pre><p>En este caso, parece que valorSeleccionado sería un numero — el id del seleccionado.</p><p>Sin embargo, lo que quiero es vincular al objecto país para el que valorSeleccionado es el objecto y no el id. &nbsp;He intentado esto:</p><pre><code class="language-ts">&lt;option *ngFor="#c de paises" value="c"&gt;{{c.nombre}}&lt;;/option&gt;</code></pre><p>pero parece que no funciona. Parece que pone un objeto en mi valorSeleccionado — pero no el objeto que espero. Lo puedes ver en mi <a href="http://plnkr.co/edit/HGRGv33EFwxDsSnELofk?p=preview" rel="noopener">Plunker</a>.</p><p>También he intentado cambiar el evento change para asignar el objeto yo mismo basado en el id; pero parece que el evento sucede antes de que se haya vinculado ngModel con el valor actualizado — en ese momento no tengo acceso al valor nuevo.</p><p>Hay una forma limpia de vincular un elemento seleccionado a un objeto de Angular 2?</p><blockquote><a href="https://stackoverflow.com/users/217408" rel="noopener"><strong><strong><em><em>Günter Zöchbauer</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (361+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><pre><code class="language-ts">&lt;h1&gt;Mi Aplicacion&lt;/h1&gt;
&lt;select [(ngModel)]="valorSeleccionado"&gt;
  &lt;option *ngFor="let p of paises" [ngValue]="p"&gt;{{p.nombre}}&lt;/option&gt;
&lt;/select&gt;</code></pre><p><strong><strong><a href="https://plnkr.co/edit/njGlIV?p=preview">Plunker </a></strong></strong></p><p>NOTA: puedes usar &nbsp;<code>[ngValue]="p"</code> en lugar de &nbsp;<code>[ngValue]="p.id"</code> donde p es el objeto para el país.</p><p><code>[value]="..."</code> solamente acepta cadenas<br><code>[ngValue]="..."</code> acepta cualquier tipo</p><p><strong>actualización</strong></p><p>Si el <code>value</code> es un objeto, la instancia preseleccionada debe ser identica a uno de los valores.</p><p><strong>desde <strong>4.0.0-beta.7</strong> también se puede comparar así:</strong></p><pre><code class="language-ts">&lt;select [compareWith]="compareFn" ...</code></pre><p>Cuidado si quieres acceder a <code>this</code> dentro de <code>compareFn</code>.</p><pre><code class="language-ts">compareFn = this._compareFn.bind(this);

// o 
// compareFn = (a, b) =&gt; this._compareFn(a, b);

_comareFn((a, b) {
   if(this.x ...) {
     ...
}</code></pre><p><a href="https://stackoverflow.com/questions/35945001" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="declarationsprovsngmodule">¿Cuál es la diferencia entre declaraciones, proveedores e importación (import) en NgModule?</h3><!--kg-card-end: html--><blockquote>188+ votos<em><em>? 5</em></em>5,432+ vistas<br><em><em><a href="https://stackoverflow.com/users/2822252/ramesh-papaganti"><strong><strong>Ramesh Papaganti</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy intentando entender Angular (también llamado Angular2+), y me he encontrado esto. &nbsp;</p><p>@Module</p><ol><li>Imports</li><li>Declarations</li><li>Providers</li></ol><blockquote><a href="https://stackoverflow.com/users/217408" rel="noopener"><strong><strong><em><em>Günter Zöchbauer</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (277+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong>Conceptos de <strong>Angular</strong></strong></p><ul><li><code>imports</code> hace que las declaraciones exportadas (exports) de otros módulos estén disponibles en el módulo actual</li><li><code>declarations</code> : se usan para crear directives (incluyendo componentes y pipes) desde el módulo actual para que esten disponibles para otras directives (como otros componentes) en el mismo módulo. Los selectores de directives, componentes o conductos (pipes) solamente se comparan con el HTML si se declaran o importan.</li><li><code>providers</code> se usan para dar a conocer servicios y valores al DI (dependency injection : inyección de dependencias). Se añaden al ámbito raíz (root) y se inyectan a otros servicios o directivas que los tengan como dependencia.</li></ul><p>Un caso especial para <code>providers</code> son módulos con carga diferida que obtienen su propio inyector secundario (child). <code>providers</code> de estos tipos de módulos solo se proporcionan a estos módulos de carga diferida (no a toda la aplicación como ocurre con otros módulos).</p><ul><li><code>exports</code> hace que los componentes, directives, y pipes (conductos) esten disponibles para los modulos que añadan este módulo a <code>imports</code>. <code>exports</code> también se puede usar para re-exportar módulos como CommonModule y FormsModule, lo que se hace a menudo en módulos compartidos.</li><li><code>entryComponents</code> registra componentes para la compilación fuera de línea para que puedan usarse con <code>ViewContainerRef.createComponent()</code>. Los componentes utilizados en las configuraciones del enrutador se agregan implícitamente.</li></ul><p><strong><strong>TypeScript (ES2015) imports</strong></strong></p><p><code>import ... from 'foo/bar'</code> son para imports de TypeScript. Los necesitas cuando usas un identificador en un fichero de TypeScript que es declarado en otro fichero de TypeScript.</p><p>Los &nbsp;<code>@NgModule()</code> <code>imports</code> de Angular y el &nbsp;<code>import</code> de TypeScript son <em>conceptos diferentes.</em></p><p><code>La mayoría son simplemente la sintaxis ECMAScript 2015 (ES6) de módulo que también usa TypeScript.</code></p><p><a href="https://stackoverflow.com/questions/39062930" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="rutaactiva">En Angular, ¿Cómo se determina la ruta activa?</h3><!--kg-card-end: html--><blockquote>187+ votos<em><em>? 1</em></em>00,870+ vistas<br><em><em><a href="https://stackoverflow.com/users/1480995/michael-oryl"><strong><strong>Michael Oryl</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p><strong><strong>NOT</strong>A<strong>:</strong></strong> Hay muchas respuestas diferentes, la mayoría han sido validas en algún momento.<em><em> </em>Lo que funciona ha cambiado varias veces a medida que el equipo de Angular ha cambiado el funcionamiento del <em>Router. </em>El<em> Router </em>version <em>3.0</em> que será <strong>el</strong> <em>router </em>e<em>n Angular </em>no funciona con algunas de estas soluciones sino que &nbsp;el mismo router ofrece una solución muy simple<em>. </em>Desde <em>RC.3, </em>la solucián mas aceptada es usar<em> <code>[routerLinkActive]</code> </em>como se muestra<em> </em><a href="https://stackoverflow.com/a/37947435/1480995">aquí</a><em>.</em></em></p><p>En una aplicación de Angular (en 2.0.0-beta.0 cuando escribo esto), ¿Cómo se determina cuál es la ruta activa?</p><p>Estoy trabajando en una aplicación que usa Bootstrap 4 y necesito una forma de marcar la navegación enlaces/botones (links/buttons) como activos cuando su componente asociado es el que se muestra en la etiqueta &nbsp;<code>&lt;router-output&gt;</code> .</p><p>Sé que puedo mantener el estado yo mismo cuando se pulsa un botón, pero eso no valdría cuando tengo varias trayectorias en la misma ruta (como un menu principal y otro local en el componenete principal).</p><p>Cualquier sugerencia o enlace sería apreciado. Gracias.</p><blockquote><a href="https://stackoverflow.com/users/974981" rel="noopener"><strong><strong><em><em>jessepinho</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (229+</em></em></strong><em> votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Con el <a href="https://github.com/angular/vladivostok" rel="noopener">router nuevo de Angular</a>, puedes añadir el atributo <code>[routerLinkActive]="['tu-nombre-de-class']"</code> a todos tus enlaces:</p><pre><code>&lt;a [routerLink]="['/home']" [routerLinkActive]="['is-active']"&gt;Home&lt;/a&gt;</code></pre><p>O la forma simplificada sin el array si solo se necesita una clase:</p><pre><code>&lt;a [routerLink]="['/home']" [routerLinkActive]="'is-active'"&gt;Home&lt;/a&gt;</code></pre><p><a href="https://stackoverflow.com/questions/34323480" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="clisass">Opciones CLI SASS de Angular</h3><!--kg-card-end: html--><blockquote>187+ votos<em><em>? 1</em></em>06,289+ vistas<br><em><em><a href="https://stackoverflow.com/users/2109585/jdillon522"><strong><strong>JDillon522</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Soy nuevo en Angular y vengo de la comunidad Ember. Estoy intentando usar el nuevo Angular-CLI basado en Ember-CLI.</p><p>Necesito saber la mejor manera de trabajar con SASS en un nuevo proyecto de Angular. He intentado usar el repo <code><a href="https://github.com/aexmachina/ember-cli-sass" rel="noopener">ember-cli-sass</a></code> para ver si podía seguirlo ya que hay un número de componentes comunes enAngular-CLI que están basados en módulos de Ember-CLI.</p><p>No ha funcionado pero no estoy seguro de estar configurando las cosas bien.</p><p>Además, ¿Cuál es la mejor manera de organizar estilos en un nuevo proyecto de Angular? Estaría bien tener el fichero sass en la misma carpeta que el componente.</p><blockquote><a href="https://stackoverflow.com/users/6265549" rel="noopener"><strong><strong><em><em>Mertcan Diken</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (323+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Cuando estés creando el proyecto, utiliza esto:</p><pre><code class="language-bash">ng new Mi_Nuevo_Proyecto --style=sass</code></pre><p>Esto crea tus ficheros con el estilo sass determinado.</p><p>Si quieres tu propia sintaxis de scss crea el proyecto de esta manera :</p><pre><code class="language-bash">ng new Mi_Nuevo_Proyecto --style=scss</code></pre><p>Si estás cambiando el estilo en tu proyecto:</p><pre><code class="language-bash">ng set defaults.styleExt scss</code></pre><p>CLI hace el resto.</p><p><a href="https://stackoverflow.com/questions/36220256" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="changedetectionmanual">Activar la detección de cambios en Angular  manualmente </h3><!--kg-card-end: html--><blockquote>186+ votos<em><em>? 1</em></em>02,556+ vistas<br><em><em><a href="https://stackoverflow.com/users/515279/jz87"><strong><strong>jz87</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy escribiendo un componente en Angular con la propierdad <code>Mode(): string</code>. Me gustaría darle un valor programáticamente y no como respuesta a un evento. El problema es que no teniendo un evento del navegador, una plantilla enlazando a <code>{{Mode}}</code> no se muestra actualizada. ¿hay alguna manera de activar el cambio manualmente?</p><blockquote><a href="https://stackoverflow.com/users/215945" rel="noopener"><strong><strong><em><em>Mark Rajcok</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (345+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Prueba alguna de estas:</p><ul><li><code><a href="https://angular.io/docs/ts/latest/api/core/index/ApplicationRef-class.html#!#tick-anchor" rel="noopener">ApplicationRef.tick()</a></code> - similar a <code>$rootScope.$digest()</code> de AngularJS's-- i.e., chequear el árbol de herarquía completo.</li><li><code><a href="https://angular.io/docs/ts/latest/api/core/index/NgZone-class.html#!#run-anchor" rel="noopener">NgZone.run(callback)</a></code> - similar a <code>$rootScope.$apply(callback)</code> -- i.e., evalua la función de callback dentro de la zona de Angular. Creo, pero no lo sé seguro, que esto acaba comprobando todo el árbol del componente después de ejecutar la función callback.</li><li><code><a href="https://angular.io/docs/ts/latest/api/core/index/ChangeDetectorRef-class.html#!#detectChanges-anchor" rel="noopener">ChangeDetectorRef.detectChanges()</a></code> - similar a <code>$scope.$digest()</code> -- i.e., comprueba solamente este componente y sus hijos.</li></ul><p>Puedes inyecar <code>ApplicationRef</code>, <code>NgZone</code>, o <code>ChangeDetectorRef</code> en tu componente.</p><p><a href="https://stackoverflow.com/questions/34827334" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="angulartypescript">Angular y Typescript: No se pueden encontrar los nombres.</h3><!--kg-card-end: html--><blockquote>184+ votos<em><em>? 1</em></em>81,472+ vistas<br><em><em><a href="https://stackoverflow.com/users/4997649/user233232"><strong><strong>user233232</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy usando Angular (versión 2) con TypeScript (versión 1.6) y al compilar me salen estos errores:</p><pre><code class="language-bash">Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/change_detection/parser/locals.d.ts(4,42): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/collection.d.ts(1,25): Error TS2304: Cannot find name 'MapConstructor'.
    node_modules/angular2/src/core/facade/collection.d.ts(2,25): Error TS2304: Cannot find name 'SetConstructor'.
    node_modules/angular2/src/core/facade/collection.d.ts(4,27): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/collection.d.ts(4,39): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/collection.d.ts(7,9): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/collection.d.ts(8,30): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/collection.d.ts(11,43): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/collection.d.ts(12,27): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/collection.d.ts(14,23): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/collection.d.ts(15,25): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/collection.d.ts(94,41): Error TS2304: Cannot find name 'Set'.
    node_modules/angular2/src/core/facade/collection.d.ts(95,22): Error TS2304: Cannot find name 'Set'.
    node_modules/angular2/src/core/facade/collection.d.ts(96,25): Error TS2304: Cannot find name 'Set'.
    node_modules/angular2/src/core/facade/lang.d.ts(1,22): Error TS2304: Cannot find name 'BrowserNodeGlobal'.
    node_modules/angular2/src/core/facade/lang.d.ts(33,59): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/facade/promise.d.ts(1,10): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/facade/promise.d.ts(3,14): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/facade/promise.d.ts(8,32): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/facade/promise.d.ts(9,38): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/facade/promise.d.ts(10,35): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/facade/promise.d.ts(10,93): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/facade/promise.d.ts(11,34): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/facade/promise.d.ts(12,32): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/facade/promise.d.ts(12,149): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/facade/promise.d.ts(13,43): Error TS2304: Cannot find name 'Promise'.
    node_modules/angular2/src/core/linker/element_injector.d.ts(72,32): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/element_injector.d.ts(74,17): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/element_injector.d.ts(78,184): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/element_injector.d.ts(83,182): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/element_injector.d.ts(107,37): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/proto_view_factory.d.ts(27,146): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/view.d.ts(52,144): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/view.d.ts(76,79): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/view.d.ts(77,73): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/view.d.ts(94,31): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/view.d.ts(97,18): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/view.d.ts(100,24): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/view.d.ts(103,142): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/linker/view.d.ts(104,160): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/render/api.d.ts(281,74): Error TS2304: Cannot find name 'Map'.
    node_modules/angular2/src/core/zone/ng_zone.d.ts(1,37): Error TS2304: Cannot find name 'Zone'.</code></pre><p>Este es el código:</p><pre><code class="language-ts">import 'reflect-metadata';
import {bootstrap, Component, CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/core';
@Component({
  selector: 'mi-app',
  template: '&lt;input type="text" [(ng-model)]="titulo" /&gt;&lt;h1&gt;{{titulo}}&lt;/h1&gt;',
  directives: [ CORE_DIRECTIVES ]
})
class AppComponent {
  titulo :string;
  
  constructor() {
    this.titulo = 'hola angular 2';
  }
}
bootstrap(AppComponent);</code></pre><blockquote><a href="https://stackoverflow.com/users/390330" rel="noopener"><strong><strong><em><em>basarat</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (50+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Un problema conocido,</p><p>La razón principal: el fichero <code>.d.ts</code> incluido implícitamente con TypeScript varía con el objetivo de compilación, así que se necesitan más variables de entorno cuando el objetivo es <code>es5</code> incluso si las cosas están presentes en runtimes (e.g. chrome). </p><p><a href="https://stackoverflow.com/questions/33332394" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="moduleid">Angular — ¿Cuál es el significado de module.id en el componente?</h3><!--kg-card-end: html--><blockquote>181+ votos<em><em>? 5</em></em>4,337+ vistas<br><em><em><a href="https://stackoverflow.com/users/2837412/nishchit-dhanani"><strong><strong>Nishchit Dhanani</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>En una aplicación de Angular, he visto que <code>@Component</code> tiene la propiedad<code>moduleId</code>. ¿Qué significa?</p><p>Y cuando <code>module.id</code> no está definida en ningún sitio, la app aún funciona. ¿Cómo puede seguir funcionando?</p><pre><code class="language-ts">@Component({
  moduleId: module.id,
  selector: 'ng-app',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  directives: [AppComponent]
});</code></pre><blockquote><a href="https://stackoverflow.com/users/2837412" rel="noopener"><strong><strong><em><em>Nishchit Dhanani</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (145+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>El lanzamiento beta de Angular (desde la versión 2-alpha.51) admite activos relativos para componentes, como <strong><strong>templateUrl</strong></strong> y &nbsp;<strong><strong>styleUrls</strong></strong> en &nbsp;<code>@Component</code>.</p><p><code>module.id</code> funciona cuando se usa CommonJS. No debe preocuparte como funciona.</p><p><code><strong>Recuerda</strong>: establecer moduleId: module.id en @Component es la clave aquí. Si no tienes eso, Angular 2 busca tus ficheros a nivel de la raíz.</code></p><p><strong>Actualizado a <strong>16 Sep 2016:</strong></strong></p><p><code>Si estás usando <strong><strong>webpack</strong></strong> para empaquetar no necesitas module.id en @Component. Webpack lo añade automáticamente al final del paquete.</code></p><p><a href="https://stackoverflow.com/questions/37178192" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="getnewselection">¿Cómo se puede obtener una nueva selección en "select" en Angular 2?</h3><!--kg-card-end: html--><blockquote>175+ votos<em><em>? 2</em></em>03,064+ vistas<br><em><em><a href="https://stackoverflow.com/users/2000548/hongbo-miao"><strong><strong>Hongbo Miao</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy usando Angular 2 (TypeScript).</p><p>Quiero hacer algo para una selección nueva, pero cuando llego a onChange() siempre tiene la última selección. ¿Cómo puedo obtener la nueva?</p><pre><code class="language-ts">&lt;select [(ngModel)]="dispositivoSeleccionado" (change)="onChange($event)"&gt;
    &lt;option *ngFor="#i of dispositivos"&gt;{{i}}&lt;/option&gt;
&lt;/select&gt;

onChange($event) {
    console.log(this.dispositivoSeleccionado);
    // Aqui quiero hacer algo para el nuevo, 
    // pero me sale el anterior, no lo que acabo de seleccionar
}</code></pre><blockquote><a href="https://stackoverflow.com/users/215945" rel="noopener"><strong><strong><em><em>Mark Rajcok</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (370+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Si no necesitas enlace de datos bidireccional:</p><pre><code class="language-ts">&lt;select (change)="onChange($event.target.value)"&gt;
    &lt;option *ngFor="let i of dispositivos"&gt;{{i}}&lt;/option&gt;
&lt;/select&gt;

onChange(valorDispositivo) {
    console.log(valorDispositivo);
}</code></pre><p>Para enlace de datos bidireccional, &nbsp;separa el enlace del evento y la propiedad:</p><pre><code class="language-ts">&lt;select [ngModel]="dispositivoSeleccionado" (ngModelChange)="onChange($event)" name="sel2"&gt;
    &lt;option [value]="i" *ngFor="let i of dispositivo"&gt;{{i}}&lt;/option&gt;
&lt;/select&gt;

export class AppComponent {
  dispositivos = 'uno dos tres'.split(' ');
  dispositivoSeleccionado = 'dos';
  onChange(nuevoValor) {
    console.log(nuevoValor);
    this.dispositivoSeleccionado = nuevoValor;
    // ... otras cosas  ...
}</code></pre><p>Si <code>dispositivos</code> es un arreglo de objectos, enlaza <code>ngValue</code> en lugar de <code>value</code>:</p><pre><code class="language-ts">&lt;select [ngModel]="dispositivoSeleccionadoObj" (ngModelChange)="onChangeObj($event)" name="sel3"&gt;
  &lt;option [ngValue]="i" *ngFor="let i of dispositivosObjectos"&gt;{{i.nombre}}&lt;/option&gt;
&lt;/select&gt;
{{dispositivoSeleccionadoObj | json}}

export class AppComponent {
  dispositivosObjectos = [{nombre: 1}, {nombre: 2}, {nombre: 3}];
  dispositivoSeleccionadoObj = this.dispositivosObjectos[1];
  onChangeObj(nuevoObj) {
    console.log(nuevoObj);
    this.dispositivoSeleccionadoObj = nuevoObj;
    // ... otras cosas ...
  }
}</code></pre><p><a href="http://plnkr.co/edit/VbJUBkqAlS8UPVgh4bqV?p=preview" rel="noopener">Plunker</a> — no usa <code>&lt;form&gt;</code><br><a href="http://plnkr.co/edit/pv5j4b1NFyTGFkxHUSga?p=preview">Plunker</a> - usa <code>&lt;form&gt;</code> y usa las nuevas forms API.</p><p><a href="https://stackoverflow.com/questions/33700266" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="cantbindngForIn">Excepción de Angular: Can’t bind to ‘ngForIn’ since it isn’t a known native property (No se puede vincular a 'ngForIn' porque no es una propiedad nativa conocida.</h3><!--kg-card-end: html--><blockquote>172+ votos<em><em>? 4</em></em>8,252+ vistas<br><em><em><a href="https://stackoverflow.com/users/215945/mark-rajcok"><strong><strong>Mark Rajcok</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>¿Qué estoy haciendo mal?</p><pre><code class="language-ts">import {bootstrap, Component} from 'angular2/angular2'

@Component({
  selector: 'conf-charlas',
  template: `&lt;div *ngFor="let charla in charlas"&gt;
     {{charla.titulo}} by {{charla.orador}}
     &lt;p&gt;{{charla.descripcion}}
   &lt;/div&gt;`
})
class ConfCharlas {
  talks = [ {titulo: 't1', orador: 'Brian', descripcion: 'charla 1'},
            {titulo: 't2', orador: 'Julie', descripcion: 'charla 2'}];
}
@Component({
  selector: 'mi-app',
  directives: [ConfCharlas],
  template: '&lt;conf-charlas&gt;&lt;/conf-charlas&gt;'
})
class App {}
bootstrap(App, [])</code></pre><p>El error:</p><pre><code class="language-bash">EXCEPTION: Template parse errors:
Can't bind to 'ngForIn' since it isn't a known native property
("&lt;div [ERROR -&gt;]*ngFor="let charla in charlas"&gt;</code></pre><blockquote><a href="https://stackoverflow.com/users/215945" rel="noopener"><strong><strong><em><em>Mark Rajcok</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (403+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Dado que esta es por lo menos la tercera vez que he perdido más de 5 minutos en este problema, he pensado en publicar las preguntas y respuestas. Espero que ayude a alguien más en el futuro... ¡probablemente a mí!</p><p>Puse <code>in</code> en lugar de <code>of</code> en el ngFor.</p><p><strong>Antes de <strong>2-beta.17</strong></strong>, debería ser:</p><pre><code>&lt;div *ngFor="#charla of charlas"&gt;</code></pre><p><em>En <em>beta.17, </em>usa la sintaxis <em><code>let</code> </em>en lugar de<em> <code>#</code>. </em>Mira la ACTUALIZACIÓN más abajo<em>.</em></em></p><p>Date cuenta que la sintaxis ngFor se convierte en:</p><pre><code class="language-ts">&lt;template ngFor #charla [ngForOf]="charlas"&gt;
  &lt;div&gt;...&lt;/div&gt;
&lt;/template&gt;</code></pre><p>Si usamos <code>in</code> , se convierte en</p><pre><code class="language-ts">&lt;template ngFor #charla [ngForIn]="charlas"&gt;
  &lt;div&gt;...&lt;/div&gt;
&lt;/template&gt;</code></pre><p>Ya que <code>ngForIn</code> no es una directive con una propiedad de input con el mismo nombre (como <code>ngIf</code>), Angular intenta ver si es una propiedad conocida (nativa) del elemento <code>template</code> y si no lo es, sale el error.</p><p><strong>ACTUALIZACIÓN</strong>— en &nbsp;2-beta.17, usa &nbsp;<code>let</code> en lugar de <code>#</code>. Esto cambia lo siguiente:</p><pre><code>&lt;div *ngFor="let charla of charlas"&gt;</code></pre><p>Date cuenta de que ngFor se convierte en:</p><pre><code class="language-ts">&lt;template ngFor let-charla [ngForOf]="charlas"&gt;
  &lt;div&gt;...&lt;/div&gt;
&lt;/template&gt;</code></pre><p>Si usas &nbsp;<code>in</code> se convierte en</p><pre><code class="language-ts">&lt;template ngFor let-charla [ngForIn]="charlas"&gt;
  &lt;div&gt;...&lt;/div&gt;
&lt;/template&gt;</code></pre><p><a href="https://stackoverflow.com/questions/34561168" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="ngifngfor">*ngIf y *ngFor en el mismo elemento causa un error</h3><!--kg-card-end: html--><blockquote>171+ votos<em><em>? 8</em></em>5,728+ vistas<br><em><em><strong><strong><a href="https://stackoverflow.com/users/1128290/garethdn">garethdn</a> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Tengo un problema usando los <code>*ngFor</code> y <code>*ngIf</code> de Angular si los uso en el mismo elemento.</p><p>Cuando intento recorrer la colección con <code>*ngFor</code>, la colección se ve como <code>null</code> y da error al intentar acceder a sus propiedades.</p><pre><code class="language-ts">@Component({
  selector: 'shell',
  template: `
    &lt;h3&gt;Shell&lt;/h3&gt;&lt;button (click)="toggle()"&gt;Toggle!&lt;/button&gt;
    
    &lt;div *ngIf="muestra" *ngFor="let cosa of cosas"&gt;
      {{log(cosa)}}
      &lt;span&gt;{{cosa.nombre}}&lt;/span&gt;
    &lt;/div&gt;
  `
})

export class ShellComponent implements OnInit {

  public cosas:any[] = [];
  public muestra:boolean = false;
  
  constructor() {}
  
  ngOnInit() {
    this.cosas = [
      { nombre: 'abc', id: 1 },
      { nombre: 'huo', id: 2 },
      { nombre: 'bar', id: 3 },
      { nombre: 'foo', id: 4 },
      { nombre: 'thing', id: 5 },
      { nombre: 'other', id: 6 },
    ]
  }
  
  toggle() {
    this.muestra = !this.muestra;
  }
  
  log(cosa) {
    console.log(cosa);
  }
  
}</code></pre><p>Sé que lo fácil es mover <code>*ngIf</code> un nivel más arriba pero para casos como recorrer una lista de elementos en una <code>ul</code>, acabaría con un <code>li</code> vacío si la colección no tiene elementos, o mi <code>li</code> está envuelto en contenedores de elementos redundantes.</p><p>Ejemplo en <a href="http://plnkr.co/edit/C5tZ8mD3iWczVvWkWycH?p=preview" rel="noopener">plnkr</a>.</p><p>Este es el error:</p><p><code>EXCEPTION: TypeError: Cannot read property 'nombre' of null in [{{cosa.nombre}} in ShellComponent@5:12]</code></p><p>¿Estoy haciendo algo mal o es un error?</p><blockquote><a href="https://stackoverflow.com/users/217408" rel="noopener"><strong><strong><em><em>Günter Zöchbauer</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (284+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Angular2 no permite más de una directiva (directive) estructural en el mismo elemento.<br>Puedes usar el elemento <code><strong><strong>&lt;ng-container&gt;</strong></strong></code> para separar los elementos con cada directiva estructural, pero <strong>no está estampada en el DOM.</strong></p><pre><code class="language-ts">&lt;ng-container *ngIf="muestra"&gt;
  &lt;div *ngFor="let cosa of cosas"&gt;
    {{log(cosa)}}
    &lt;span&gt;{{cosa.nombre}}&lt;/span&gt;
  &lt;/div&gt;
&lt;/ng-container&gt;</code></pre><p><code>&lt;ng-template&gt;</code> (<code>&lt;template&gt;</code> antes de Angular4) te deja hacer lo mismo pero de manera diferente, con una sintaxis confusa y no recomendada</p><pre><code class="language-ts">&lt;ng-template [ngIf]="muestra"&gt;
  &lt;div *ngFor="let cosa of cosas"&gt;
    {{log(cosa)}}
    &lt;span&gt;{{cosa.nombre}}&lt;/span&gt;
  &lt;/div&gt;
&lt;/ng-template&gt;</code></pre><p><a href="https://stackoverflow.com/questions/34657821" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="swatcheq">¿Cuál es el equivalente del $watch de AngularJS en Angular?</h3><!--kg-card-end: html--><blockquote>169+ votos <em><em>? 9</em></em>5,029+ vistas<br><em><em><a href="https://stackoverflow.com/users/1716567/erwin"><strong><strong>Erwin</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>En AngularJS se podían especificar watchers (observadores) para observar cambios en las variables usando &nbsp;<code>$watch</code> de <code>$scope</code>. ¿Cuál es el equivalente de observar cambios de variables (en, por ejemplo, variables de componentes) en Angular?</p><blockquote><a href="https://stackoverflow.com/users/215945" rel="noopener"><strong><strong><em><em>Mark Rajcok</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (226+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>En Angular 2, la detección de cambios es automática… <code>$scope.$watch()</code> y <code>$scope.$digest()</code> D.E.P.</p><p>Desafortunadamente, la sección de detección de cambios de la guía para desarrolladores aún no está escrita.</p><p>Aquí está como lo entiendo yo:</p><ul><li>Zone.js &nbsp;—intercepta todas las API asíncronas en el navegador (cuando Angular está corriendo). Por eso podemos usar <code>setTimeout()</code> dentro de nuestros componentes en lugar de algo como <code>$timeout</code>... porque<code>setTimeout()</code> se cambia durante en runtime.</li><li>Angular construye y mantiene un árbol de "detectores de cambio". Hay uno (class) por componente/directive. (Puede obtener acceso a este objeto inyectando <code><a href="https://angular.io/docs/ts/latest/api/core/index/ChangeDetectorRef-class.html" rel="noopener">ChangeDetectorRef</a></code>.) Estos detectores de cambios se crean cuando Angular crea componentes. Realizan un seguimiento del estado de todos tus enlaces, para ver si han cambiado. Estos son, en cierto sentido, similares a los &nbsp;<code>$watches()</code> automáticos que Angular 1 establecería para los enlaces <code>{{}}</code> en la plantilla (template).<br>A diferencia de Angular 1, el gráfico de detección de cambios es un árbol dirigido y no puede tener ciclos (esto hace que Angular 2 tenga mucho más rendimiento, como veremos a continuación.).</li><li>Cuando se dispara un evento (dentro de la zona Angular), se ejecuta el código que escribimos (la devolución de llamada del controlador de eventos).Puede actualizar cualquier tipo de datos que quiera— el modelo de la aplicació compartido/estado y/o el estado de la vista (view) del componente.</li><li>Después de eso, debido a los ganchos añadidos por Zone.js, ejecuta el algoritmo de detección de cambios de Angular. De forma predeterminada (es decir, si no está utilizando la detección de cambio <code>onPush</code> en ninguno de tus componentes), cada componente del árbol se examina una vez (TTL=1)... desde arriba, en primer orden de profundidad. (Bueno, si estás en modo desarrollador, la detección de cambios se ejecuta dos veces (TTL=2). Realiza comprobaciones de cambios en todos sus enlaces, utilizando esos objetos detectores de cambios.</li><li>Se llama a los enlaces de ciclo de vida como parte de la detección de cambios.<br>Si los datos del componente que deseas ver son una propiedad de entrada primitiva(String, boolean, number), puedes implementar <code>ngOnChanges()</code> para que se te notifique de los cambios.<br>Si la propiedad de entrada es un tipo de referencia (object, array, etc.), pero la referencia no cambió (e.g., agregaste un elemento a un arreglo existente), tendrás que implementar <code>ngDoCheck()</code> .<br>Solamente debes cambiar las propiedades del componente y/o las propiedades de los componentes descendientes (debido a la implementación de recorrido de un solo árbol -- i.e., flujo de datos unidireccional). Aqui hay un ejemplo en <a href="http://plnkr.co/edit/XWBSvE0NoQlRuOsXuOm0?p=preview" rel="noopener">plunker</a> que no lo cumple.</li><li>Para cualquier cambio de vinculación que se encuentre, los componentes se actualizan y, a continuación, se actualiza el DOM. La detección de cambios ya ha finalizado.</li><li>El navegador nota los cambios de DOM y actualiza la pantalla.</li></ul><p>Otras referencias para saber más:</p><ul><li>Savkin’s <a href="https://www.youtube.com/watch?v=jvKGQSFQf10" rel="noopener">Deteción de cambios reinventada</a> — video (puedes configurar para que se subtitule)</li><li><a href="https://www.youtube.com/watch?v=3IqtmUscE_U" rel="noopener">El video de Brian</a> y <a href="https://www.youtube.com/watch?v=V9Bbp6Hh2YE" rel="noopener">el de Miško</a> sobre Zone.js. El de Brian es sobre Zone.js. El de Miško trata sobre cómo Angular 2 usa Zone.js para implementar la detección de cambios. También habla sobre la detección de cambios en general, y un poco sobre <code>onPush</code>.</li></ul><p><a href="https://stackoverflow.com/questions/34569094" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="importlodash">Importando lodash en angular2 + aplicaciones typescript</h3><!--kg-card-end: html--><blockquote>167+ votos<em><em>? 1</em></em>04,431+ vistas<br><em><em><a href="https://stackoverflow.com/users/1854793/davy"><strong><strong>Davy</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Me está costando importar los módulos de lodash. He creado mi proyecto con npm+gulp, y sigo chocando con la misma pared. He probado con el lodash convencional, pero también lodash-es.</p><p>El paquete de lodash de npm: (tiene un fichero index.js en la carpeta raíz)</p><pre><code class="language-ts">import * as _ from 'lodash';</code></pre><p>Resultado:</p><pre><code>error TS2307: Cannot find module 'lodash'.</code></pre><p>El paquete de lodash-es de npm: (tiene un export lodash.js por defecto en la carpeta raíz)</p><pre><code>import * as _ from 'lodash-es/lodash';</code></pre><p>Resultado:</p><pre><code>error TS2307: Cannot find module 'lodash-es'.</code></pre><p>Tanto gulp como webstorm tienen el mismo problema.</p><p>Lo curioso es que esto no da error:</p><pre><code class="language-ts">import 'lodash-es/lodash';</code></pre><p>… pero no hay &nbsp;“_” …</p><p>Mi fichero tsconfig.json:</p><pre><code class="language-json">{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules"
  ]
}</code></pre><p>Mi gulpfile.js:</p><pre><code class="language-json">var gulp = require('gulp'),
    ts = require('gulp-typescript'),
    uglify = require('gulp-uglify'),
    sourcemaps = require('gulp-sourcemaps'),
    tsPath = 'app/**/*.ts';
    
gulp.task('ts', function () {
    var tscConfig = require('./tsconfig.json');
    
    gulp.src([tsPath])
        .pipe(sourcemaps.init())
        .pipe(ts(tscConfig.compilerOptions))
        .pipe(sourcemaps.write('./../js'));
});

gulp.task('watch', function() {
    gulp.watch([tsPath], ['ts']);
});

gulp.task('default', ['ts', 'watch']);</code></pre><p>Si lo entiendo bien, moduleResolution:’node’ en mi tsconfig debería apuntar los imports al fichero node_modules, donde lodash y lodash-es están instalados. También he probado maneras diferentes de importar: trayectorias (paths) absolutas, relativas, pero nada funciona. ¿alguna idea?</p><p>Si es necesario puedo poner un pequeño fichero zip.</p><blockquote><a href="https://stackoverflow.com/users/544130" rel="noopener"><strong><strong><em><em>Taytay</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (293+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Así es como se hace con Typescript 2.0: (tsd y typings están en desuso a favor de lo siguiente):</p><pre><code class="language-bash">$ npm install --save lodash

# Esto es lo nuevo: 
$ npm install --save @types/lodash</code></pre><p>Luego en tu fichero .ts:</p><p>Esto:</p><pre><code class="language-ts">import * as _ from "lodash";</code></pre><p>O esto (sugerido por @Naitik):</p><pre><code class="language-ts">import _ from "lodash";</code></pre><p>No sé seguro cual es la diferencia. Nosotros preferimos y usamos la primera sintaxis. Sin embargo, hay quien dice que a ellos no les funciona, y alguien más comentó que la segunda sintaxis es incompatible con módulos de webpack en lazy loaded. </p><p>Editado el 27th Febrero, 2017:</p><p>Según @Koert abajo, <code>import * as _ from "lodash";</code> es la única sintaxis que funciona con Typescript 2.2.1, lodash 4.17.4, y @types/lodash 4.14.53. Dice que la otra sintaxis da el error "has no default export" (no tiene export por defecto).</p><p><a href="https://stackoverflow.com/questions/34660265" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="routechange">¿Cómo se detecta un cambio de ruta en Angular?</h3><!--kg-card-end: html--><blockquote>160+ votos<em><em>? 1</em></em>08,593+ vistas<br><em><em><a href="https://stackoverflow.com/users/1590389/angularm"><strong><strong>AngularM</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Quiero detectar un cambio de ruta en <code>AppComponent</code>.</p><p>A partir de entonces, comprobaré el token de usuario global para ver si ha iniciado sesión. Luego, puedo redirigir al usuario si no ha iniciado sesión.</p><blockquote><a href="https://stackoverflow.com/users/1048274" rel="noopener"><strong><strong><em><em>Ludohen</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (223+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>En Angular 2 puedes <code>subscribe</code> (evento Rx) a una instancia de Router. Entonces puesdes hacer cosas como esta:</p><pre><code class="language-ts">class MiClase {
  constructor(private router: Router) {
    router.subscribe((val) =&gt; /*lo que sea*/)
  }
}</code></pre><p><strong><strong>Edit</strong>ado</strong> (desde rc.1)</p><pre><code class="language-ts">class MiClase {
  constructor(private router: Router) {
    router.changes.subscribe((val) =&gt; /*lo que sea*/)
  }
}</code></pre><p><strong><strong>Edit</strong>ado<strong> 2</strong></strong> (desde 2.0.0)</p><pre><code class="language-ts">class MiClase {
  constructor(private router: Router) {
    router.events.subscribe((val) =&gt; {
        // ver tambien
        console.log(val instanceof NavigationEnd) 
    });
  }
}</code></pre><p><a href="https://stackoverflow.com/questions/33520043" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="globalevents">Global Events en Angular (eventos globales)</h3><!--kg-card-end: html--><blockquote>157+ votos <em><em>? 8</em></em>3,980+ vistas<br><em><em><a href="https://stackoverflow.com/users/3368477/skovmand"><strong><strong>skovmand</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>¿hay equivalente a <code>$scope.emit()</code> o <code>$scope.broadcast()</code> en Angular?</p><p>Conozco la funcionalidad de <code>EventEmitter</code> , pero según lo entiendo yo, eso emite un evento al elemento HTML padre.</p><p>¿Qué pasa si necesito comunicarme entre elementos al misno nivel (siblings) o entre un componente en la raíz del DOM y un elemento anidado a varios niveles de profundidad? </p><blockquote><a href="https://stackoverflow.com/users/3661630" rel="noopener"><strong><strong><em><em>pixelbits</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (304+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>No hay equivalente a <code>$scope.emit()</code> o <code>$scope.broadcast()</code> de AngularJS. EventEmitter dentro de un componente es bastante parecido, pero como tu dices, solamente emite al elemento padre inmediato.</p><p>En Angular, hay otras alternativas que trato de explicar abajo.</p><p>Los enlaces con @Input() permiten que el modelo de aplicación se conecte en un elemento gráfico (raíz a hojas). El comportamiento por defecto de un detector de cambios de un componente es propagar todos los cambios a un modelo de la aplicación para todos los enlaces desde cualquier componente conectado.</p><p>Aclarando: Hay dos tipos de modelos: View Models (vista) y Application Models (aplicación). Uno de aplicación se conecta con enlaces @Input(). Uno de view &nbsp;(vista) es una propiedad de componente (no decorado con @Input()) que está enlazado en la plantilla del componente.</p><p>Contestando a tus preguntas:</p><p>¿Qué pasa si necesito comunicarme entre componentes hermanos?</p><ol><li><strong><strong>Application Model</strong> Compartido</strong>: Los hermanos pueden comunicarse a través de un modelo de aplicación compartida (al igual que angular 1). Por ejemplo, cuando un hermano realiza un cambio en un modelo, el otro hermano que tiene enlaces al mismo modelo se actualiza automáticamente.</li><li><strong>Eventos de <strong>Component</strong>e</strong>: Los componentes hijos pueden emitir un evento al componente padre mediante enlaces @Output(). El componente principal puede manejar el evento y manipular el modelo de aplicación o su propio modelo de vista. Cambios a un Application Model se propagan automáticamente a todos los componentes que se unen directa o indirectamente al mismo modelo.</li><li><strong>Eventos de <strong>Servic</strong>io</strong>: Los componentes pueden suscribirse a eventos de servicio. Por ejemplo, dos componentes hermanos pueden suscribirse al mismo evento de servicio y responder modificando sus respectivos modelos. Más sobre esto a continuación.</li></ol><p>¿Cómo puedo comunicarme entre un componente raíz y un componente anidado a varios niveles de profundidad?</p><ol><li><strong><strong>Application Model</strong> Compartido</strong>: El modelo de aplicación se puede pasar del componente raíz a subcomponentes profundamente anidados a través de enlaces @Input(). Los cambios en un modelo desde cualquier componente se propagarán automáticamente a todos los componentes que comparten el mismo modelo.</li><li><strong>Eventos de <strong>Servic</strong>io</strong>: También puede mover EventEmitter a un servicio compartido, lo que permite que cualquier componente inyecte el servicio y se suscriba al evento. De esa forma, un componente Root puede llamar a un método de servicio (normalmente mutando el modelo), que a su vez emite un evento. Varios niveles más abajo, un componente secundario que también inyectó el servicio y se suscribió al mismo evento, puede manejarlo. Cualquier controlador de eventos que cambie un Application Model compartido, se propagará automáticamente a todos los componentes que dependen de él. Esto debe ser lo más parecido a <code>$scope.broadcast()</code> de Angular 1. La siguiente sección describe esta idea con más detalle.</li></ol><p><strong><strong>E</strong>jemplo de un servicio<strong> Observable </strong>que usa eventos de servicio para propagar los cambios</strong></p><p>Cuando se añade un ElementoPendiente, el servicio notifica a sus suscriptores.</p><pre><code class="language-ts">export class ElementoPendiente {
    constructor(public nombre: string, public hecho: boolean) {
    }
}
export class ServicioPendiente {
    public elementosAnadidos$: EventEmitter&lt;ElementoPendiente&gt;;
    private pendienteLista: ElementoPendiente[] = [];
    
    constructor() {
        this.elementosAnadidos$ = new EventEmitter();
    }
    
    public lista(): ElementoPendiente[] {
        return this.pendienteLista;
    }
    
    public anadir(elem: ElementoPendiente): void {
        this.pendienteLista.push(elem);
        this.elementosAnadidos$.emit(elem);
    }
}</code></pre><p>Un elemento en la raíz se suscribiría de esta forma:</p><pre><code class="language-ts">export class RaizComponent {
    private elementoAnadido: ElementoPendiente;
    constructor(servicioPendiente: ServicioPendiente) {
        servicioPendiente.elementosAnadidos$.subscribe(elem =&gt; this.onElementoAnadido(elem));
    }
    
    private onElementoAnadido(elem: ElementoPendiente): void {
        // haz algo con el elemento anandido
        this.elementoAnadido = elem;
    }
}</code></pre><p>Un elemento hijo unos cuantos niveles más abajo se suscribiría así:</p><pre><code class="language-ts">export class NietoComponent {
    private elemementoAnadido: ElementoPendiente;
    constructor(servicioPendiente: ServicioPendiente) {
        servicioPendiente.elementosAnadidos$.subscribe(elem =&gt; this.onElementoAnadido(elem));
    }
    
    private onElementoAnadido(elem: ElementoPendiente): void {
        // haz algo con el elemento anadido
        this.elemementoAnadido = elem;
    }
}</code></pre><p>Este es el componente que llama al servicio para lanzar el evento (puede estar en cualquier sitio del componente):</p><pre><code class="language-ts">@Component({
    selector: 'lista-pendiente',
    template: `
         &lt;ul&gt;
            &lt;li *ngFor="#item of modelo"&gt; {{ item.nombre }}
            &lt;/li&gt;
         &lt;/ul&gt;
        &lt;br /&gt;
        Anadir elemento &lt;input type="text" #txt /&gt; &lt;button (click)="anadir(txt.value); txt.value='';"&gt;Anadir&lt;/button&gt;
    `
})
export class TriggeringComponent{
    private modelo: ElementoPendiente[];
    
    constructor(private servicioPendiente: ServicioPendiente) {
        this.modelo = servicioPendiente.lista();
    }
    
    anadir(value: string) {
        this.servicioPendiente.add(new ElementoPendiente(value, false));
    }
}</code></pre><p><a href="https://stackoverflow.com/questions/34700438" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="systemjswebpack">¿Cuales son algunas diferencias entre SystemJS y Webpack?</h3><!--kg-card-end: html--><blockquote>155+ votos<em><em>? 6</em></em>0,183+ vistas<br><em><em><a href="https://stackoverflow.com/users/2516399/smartmouse"><strong><strong>smartmouse</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy creando mi primera aplicación de Angular y me pregunto por qué necesitamos los cargadores de módulos. He intentando encontrarlo en Google y no entiendo por qué hay que instalar uno de ellos para correr la aplicación.</p><p>¿No sería suficiente usar &nbsp;<code>import</code> para cargar cosas de los módulos de node?</p><p>He encontrado este ejemplo en un tutorial de Angular (que usa SystemJS) y me hace usar el fichero <code>systemjs.config.js</code> :</p><pre><code class="language-js">/**
 * configuracion para ejemplos
 * ajustar como sea necesario para tu aplicacion
 */
(function(global) {
  // map le dice al System Loader donde buscar
  var map = {
    'app':                        'transpiled', // 'dist',
    '@angular':                   'node_modules/@angular',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    'rxjs':                       'node_modules/rxjs'
  };
  // packages le dice al System loader como cargar cuando no hay nombre de fichero y/o extension
  var packages = {
    'app':                        { main: 'main.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
  };
  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'forms',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];
  // ficheros individuales (~300 requests):
  function packIndex(pkgName) {
    packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
  }
  // empaquetados (~40 requests):
  function packUmd(pkgName) {
    packages['@angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
  }
  // la mayoria de entornos deberian usar UMD; algunos (Karma) necesitan los ficheros individuales
  var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
  // Anadir para los paquetes de Angular
  ngPackageNames.forEach(setPackageConfig);
  var config = {
    map: map,
    packages: packages
  };
  System.config(config);
})(this);</code></pre><p>¿Por qué necesitamos este archivo de configuración?<br>¿Por qué necesitamos SystemJS (o WebPack u otras)?<br>Finalmente, en tu opinión, ¿qué es mejor?</p><blockquote><a href="https://stackoverflow.com/users/1873365" rel="noopener"><strong><strong><em><em>Thierry Templier</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (97+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Si vas a la página de GitHub de SystemJS, verás la descripción de la herramienta:</p><p><code>Universal dynamic module loader - carga ES6 modules, AMD, CommonJS y global scripts en el navegador y NodeJS.</code></p><p>Como usas módulos en TypeScript o ES6, &nbsp;necesitas el cargador de módulos. En el caso de SystemJS, &nbsp;<code>systemjs.config.js</code> nos permite configurar la forma en que se emparejan los nombres de los módulos con sus archivos correspondientes.</p><p>Este archivo de configuración (y SystemJS) es necesario si quieres importar el módulo principal de su aplicación explícitamente:</p><pre><code class="language-html">&lt;script&gt;
  System.import('app').catch(function(err){ console.error(err); });
&lt;/script&gt;</code></pre><p>Cuando usas TypeScript, y configuras el compilador para el módulo <code>commonjs</code> module, el compilador crea código que ya no esta basado en SystemJS. En este ejemplo, el compilador de TypeScript sería así:</p><pre><code class="language-json">{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs", // &lt;------
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  }
}</code></pre><p>Webpack es un empaquetador de módulos flexible. Esto quiere decir que llega más lejos y no solamente se ocupa de módulos, también proporciona una manera de empaquetar tu aplicación (concat files, uglify files, …). También proporciona un servidor de desarrolo con carga recarga para el desarrollo.</p><p>SystemJS y Webpack son diferentes pero con SystemJS, te queda más trabajo por hacer (con <a href="http://gulpjs.com/" rel="noopener">Gulp</a> o <a href="https://github.com/systemjs/builder" rel="noopener">SystemJS builder</a> por ejemplo) para empaquetar tu aplicación de Angular2 para producción.</p><p><a href="https://stackoverflow.com/questions/38263406" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="cantfindpromise">Angular: Can’t find Promise, Map, Set and Iterator (No se puede encontrar Promise, Map, Set y Iterator)</h3><!--kg-card-end: html--><blockquote>154+ votos<em><em>? 9</em></em>0,201+ vistas<br><em><em><a href="https://stackoverflow.com/users/806963/stav-alfi"><strong><strong>Stav Alfi</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Después de instalar Angular, el compilador de Typescript me da errores de que no encuentra &nbsp;<code>Promise</code>, <code>Map</code>, <code>Set</code> y <code>Iterator</code>.</p><p>Hasta ahora los he ignorado pero ahora necesito que <code>Promise</code> funcione.</p><pre><code class="language-ts">import {Component} from 'angular2/core';
@Component({
    selector: 'saludos-cmp',
    template: `&lt;div&gt;{{ asyncSaludos | async}}&lt;/div&gt;`
})
export class SaludosCmp {
    asyncSaludos: Promise&lt;string&gt; = new Promise(resolve =&gt; {
// despues de 1 segundo, la promise resuelve
        window.setTimeout(() =&gt; resolve('hola'), 1000);
    });
}

informacion adicional:
npm -v is 2.14.12
node -v is v4.3.1
typescript v is 1.6</code></pre><p><strong><strong>The errors:</strong></strong></p><pre><code class="language-bash">................ERROS OF MY CODE.................
    C:\Users\armyTik\Desktop\angular2\greeting_cmp.ts
    Error:(7, 20) TS2304: Cannot find name 'Promise'.
    Error:(7, 42) TS2304: Cannot find name 'Promise'.
    .........................................
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\platform\browser.d.ts
    Error:(77, 90) TS2304: Cannot find name 'Promise'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\core\application_ref.d.ts
    Error:(83, 60) TS2304: Cannot find name 'Promise'.
    Error:(83, 146) TS2304: Cannot find name 'Promise'.
    Error:(96, 51) TS2304: Cannot find name 'Promise'.
    Error:(96, 147) TS2304: Cannot find name 'Promise'.
    Error:(133, 90) TS2304: Cannot find name 'Promise'.
    Error:(171, 81) TS2304: Cannot find name 'Promise'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\core\change_detection\parser\locals.d.ts
    Error:(3, 14) TS2304: Cannot find name 'Map'.
    Error:(4, 42) TS2304: Cannot find name 'Map'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\core\debug\debug_node.d.ts
    Error:(14, 13) TS2304: Cannot find name 'Map'.
    Error:(24, 17) TS2304: Cannot find name 'Map'.
    Error:(25, 17) TS2304: Cannot find name 'Map'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\core\di\provider.d.ts
    Error:(436, 103) TS2304: Cannot find name 'Map'.
    Error:(436, 135) TS2304: Cannot find name 'Map'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\core\linker\compiler.d.ts
    Error:(12, 50) TS2304: Cannot find name 'Promise'.
    Error:(16, 41) TS2304: Cannot find name 'Promise'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\core\linker\dynamic_component_loader.d.ts
    Error:(108, 136) TS2304: Cannot find name 'Promise'.
    Error:(156, 150) TS2304: Cannot find name 'Promise'.
    Error:(197, 128) TS2304: Cannot find name 'Promise'.
    Error:(203, 127) TS2304: Cannot find name 'Promise'.
    Error:(204, 141) TS2304: Cannot find name 'Promise'.
    Error:(205, 119) TS2304: Cannot find name 'Promise'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\core\render\api.d.ts
    Error:(13, 13) TS2304: Cannot find name 'Map'.
    Error:(14, 84) TS2304: Cannot find name 'Map'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\facade\async.d.ts
    Error:(27, 33) TS2304: Cannot find name 'Promise'.
    Error:(28, 45) TS2304: Cannot find name 'Promise'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\facade\collection.d.ts
    Error:(1, 25) TS2304: Cannot find name 'MapConstructor'.
    Error:(2, 25) TS2304: Cannot find name 'SetConstructor'.
    Error:(4, 27) TS2304: Cannot find name 'Map'.
    Error:(4, 39) TS2304: Cannot find name 'Map'.
    Error:(7, 9) TS2304: Cannot find name 'Map'.
    Error:(8, 30) TS2304: Cannot find name 'Map'.
    Error:(11, 43) TS2304: Cannot find name 'Map'.
    Error:(12, 27) TS2304: Cannot find name 'Map'.
    Error:(14, 23) TS2304: Cannot find name 'Map'.
    Error:(15, 25) TS2304: Cannot find name 'Map'.
    Error:(95, 41) TS2304: Cannot find name 'Set'.
    Error:(96, 22) TS2304: Cannot find name 'Set'.
    Error:(97, 25) TS2304: Cannot find name 'Set'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\facade\lang.d.ts
    Error:(13, 17) TS2304: Cannot find name 'Map'.
    Error:(14, 17) TS2304: Cannot find name 'Set'.
    Error:(78, 59) TS2304: Cannot find name 'Map'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\facade\promise.d.ts
    Error:(2, 14) TS2304: Cannot find name 'Promise'.
    Error:(7, 32) TS2304: Cannot find name 'Promise'.
    Error:(8, 38) TS2304: Cannot find name 'Promise'.
    Error:(9, 35) TS2304: Cannot find name 'Promise'.
    Error:(9, 93) TS2304: Cannot find name 'Promise'.
    Error:(10, 34) TS2304: Cannot find name 'Promise'.
    Error:(11, 32) TS2304: Cannot find name 'Promise'.
    Error:(11, 149) TS2304: Cannot find name 'Promise'.
    Error:(12, 43) TS2304: Cannot find name 'Promise'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\http\headers.d.ts
    Error:(43, 59) TS2304: Cannot find name 'Map'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\http\url_search_params.d.ts
    Error:(11, 16) TS2304: Cannot find name 'Map'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\platform\browser\browser_adapter.d.ts
    Error:(75, 33) TS2304: Cannot find name 'Map'.
    C:\Users\armyTik\Desktop\angular2\node_modules\angular2\src\platform\dom\dom_adapter.d.ts
    Error:(85, 42) TS2304: Cannot find name 'Map'.
    C:\Users\armyTik\Desktop\angular2\node_modules\rxjs\CoreOperators.d.ts
    Error:(35, 67) TS2304: Cannot find name 'Promise'.
    Error:(50, 66) TS2304: Cannot find name 'Promise'.
    Error:(89, 67) TS2304: Cannot find name 'Promise'.
    Error:(94, 38) TS2304: Cannot find name 'Promise'.
    Error:(94, 50) TS2304: Cannot find name 'Promise'.
    C:\Users\armyTik\Desktop\angular2\node_modules\rxjs\Observable.d.ts
    Error:(46, 62) TS2304: Cannot find name 'Promise'.
    Error:(47, 42) TS2304: Cannot find name 'Iterator'.
    Error:(103, 74) TS2304: Cannot find name 'Promise'.
    Error:(103, 84) TS2304: Cannot find name 'Promise'.
    Error:(143, 66) TS2304: Cannot find name 'Promise'.
    Error:(158, 65) TS2304: Cannot find name 'Promise'.
    Error:(201, 66) TS2304: Cannot find name 'Promise'.
    Error:(206, 38) TS2304: Cannot find name 'Promise'.
    Error:(206, 50) TS2304: Cannot find name 'Promise'.
    C:\Users\armyTik\Desktop\angular2\node_modules\rxjs\observable\ForkJoinObservable.d.ts
    Error:(6, 50) TS2304: Cannot find name 'Promise'.
    Error:(7, 58) TS2304: Cannot find name 'Promise'.
    C:\Users\armyTik\Desktop\angular2\node_modules\rxjs\observable\FromObservable.d.ts
    Error:(7, 38) TS2304: Cannot find name 'Promise'.
    Error:(7, 51) TS2304: Cannot find name 'Iterator'.
    C:\Users\armyTik\Desktop\angular2\node_modules\rxjs\observable\PromiseObservable.d.ts
    Error:(9, 31) TS2304: Cannot find name 'Promise'.
    Error:(10, 26) TS2304: Cannot find name 'Promise'.</code></pre><blockquote><a href="https://stackoverflow.com/users/1949099" rel="noopener"><strong><strong><em><em>Kris Hollenbeck</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (162+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><!--kg-card-begin: html--><h3 id="rc4">Angular RC4 — Angular ^2.0.0 con Typescript 2.0.0</h3><!--kg-card-end: html--><p><em>Actualizado <em>9/19/2016</em></em></p><p>Para hacer que esto funcione con typescript 2.0.0, he hecho esto.</p><p><code>npm install --save-dev @types/core-js</code></p><p><strong><strong>tsconfig.json</strong></strong></p><pre><code class="language-json">"compilerOptions": {
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "mapRoot": "./",
    "module": "es6",
    "moduleResolution": "node",
    "noEmitOnError": true,
    "noImplicitAny": false,
    "outDir": "../dist/out-tsc",
    "sourceMap": true,
    "target": "es5",
    "typeRoots": [
      "../node_modules/@types"
    ],
    "types": [
      "core-js"
    ]
  }</code></pre><p><strong><strong>M</strong>ás sobre <strong>@types </strong>con<strong> typescript 2.0.0.</strong></strong></p><ol><li><a href="https://www.npmjs.com/~types" rel="noopener">https://www.npmjs.com/~types</a></li></ol><p>Ejemplo de Install:</p><pre><code>npm install --save-dev @types/core-js</code></pre><p><strong>Errores de identificador duplicados</strong></p><p>Esto seguramente es porque los ecmascript 6 typings ya están siendo importados desde algún otro sitio, posiblemente un versión vieja de es6-shim.</p><p>Verifica <code>typings.d.ts</code> y asegúrate de que no hay referencias a <code>es6</code>. Quita cualquier referencia a &nbsp;<code>es6</code> de tu directorio de typings si tienes uno.</p><p><strong>Por ejemplo<strong>:</strong></strong></p><p>Esto tendrá un conflicto con <code>types:['core-js']</code> en typings.json.</p><pre><code class="language-json">{
  "globalDependencies": {
    "core-js": "registry:dt/core-js#0.0.0+20160602141332" 
    // es6-shim tambien tendra conflicto
  }
}</code></pre><p><code>core-js</code> en el arreglo de types en <code>tsconfig.json</code> debería ser el único sitio de donde se importa.</p><p><strong><strong>Angular CLI 1.0.0-beta.30</strong></strong></p><p>Si usas Angular-CLI, quita el arreglo lib en <code>typings.json</code>. Esto parece que tiene un conflicto con declarar core-js en types.</p><pre><code class="language-json">"compilerOptions" : {
  ...
  // eleminado "lib": ["es6", dom"],
  ...
},
"types" : ["core-js"]</code></pre><p><strong>Usuarios de <strong>Webstorm/Intellij </strong>con<strong> Angular CLI</strong></strong></p><p>Asegúrate de que el compilador TypeScript incorporado esté deshabilitado. Esto entrará en conflicto con la CLI. Para compilar tu typescript con el CLI puedes configurar como <code>ng serve</code> .</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/YG2jiM4rYeIBDbXVSaDe3VOIdHlSAH1Z7hmN" class="kg-image" alt="YG2jiM4rYeIBDbXVSaDe3VOIdHlSAH1Z7hmN" width="800" height="448" loading="lazy"></figure><p><strong><strong>Tsconfig compilerOptions lib vs types</strong></strong></p><p>Si prefieres no instalar definiciones de core js type hay librerias de es6 que vienen incluidas con typescript. Se usan via la propiedad <code>lib: []</code> en tsconfig.</p><p><code>Nota: Si --lib no se especifica se inyecta una librería por defecto. Esta libraría inyectada es: ? For --target ES5: DOM,ES5,ScriptHost ? For --target ES6: DOM,ES6,DOM.Iterable,ScriptHost</code></p><p><strong><strong>tl;dr</strong></strong></p><p>Brevemente: &nbsp;<code>"lib": [ "es6", "dom" ]</code> o <code>"types": ["core-js"]</code> se pueden usar para resolver <code>can't find Promise,Map, Set and Iterator</code>. Sin embargo, usar ambos causará errores de identificador duplicado.</p><p><a href="https://stackoverflow.com/questions/35660498" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="detectinputchanges">¿Cómo se detecta cuando cambia un valor de @Input() en Angular?</h3><!--kg-card-end: html--><blockquote>154+ votos<em><em>? 8</em></em>9,893+ vistas<br><em><em><a href="https://stackoverflow.com/users/3604283/jon-catmull"><strong><strong>Jon Catmull</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Tengo un componente padre (<strong><strong>Categor</strong>ia<strong>Component</strong></strong>), un componente hijo (<strong><strong>videoListComponent</strong></strong>) y un ApiService.</p><p>Casi todo funciona i.e. todos los componentes pueden acceder a la API de JSON y obtener los datos relevantes para sus observables.</p><p>Ahora mismo <strong><strong>videoListComponent</strong> </strong>obtiene todos los videos, me gustaría filtrar los videos basados en su categoría, y lo consigo pasando el ID categoriaId al hijo con &nbsp;<code>@Input()</code>.</p><p>CategoriaComponent.html</p><pre><code class="language-ts">&lt;video-list *ngIf="categoria" [categoriaId]="categoria.id"&gt;&lt;/video-list&gt;</code></pre><p>Esto funciona y cuando la categoría del padre CategoriaComponent cambia, el &nbsp;valor de categoriaId se pasa con <code>@Input()</code> pero necesito detectar esto en VideoListComponent y volver a pedir (re-request) el arreglo con los videos via APIService (con el nuevo categoriaId).</p><p>En AngularJS habría usado <code>$watch</code> en la variable. ¿Cuál es la mejor manera de manejar esto?</p><blockquote><a href="https://stackoverflow.com/users/2107767" rel="noopener"><strong><strong><em><em>Alan C. S.</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (181+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong>En realidad<strong>, </strong>hay dos formas de detectar y actuar cuando un <strong>input </strong>cambia en el componente hijo en <strong>angular2+ :</strong></strong></p><ol><li><strong>Puedes usar</strong> <strong><strong>ngOnChanges() </strong></strong>como se menciona en respuestas anteriores:<br><code>@Input() categoriaId: string; ngOnChanges(cambios: SimpleChanges) { this.hazAlgo(cambios.categoriaId.currentValue); // también puedes usar categoriaId.previousValue y // categoriaId.firstChange para comparar los valores nuevos y viejos }</code></li><li>Ejemplo: Mira en <a href="https://plnkr.co/edit/LUr2bMQRhhAeuLN3R5B6?p=preview" rel="noopener">plunker</a></li><li>Además, puedes usar <strong>@I<strong>nput </strong></strong>así:<br><code>private _categoriaId: string; @Input() set categoriaId(value: string) { this._categoriaId = value; this.hazAlgo(this._categoriaId); } obtenerCategoriaId(): string { return this._categoriaId; }</code></li><li>Ejemplo: Mira en <a href="https://plnkr.co/edit/EsolgwJVuvOUx6rKk8d4?p=preview" rel="noopener">plunker</a>.</li></ol><p><strong>¿QUÉ ENFOQUE SE DEBE UTILIZAR?</strong></p><p>Si tu componente tiene varios inputs, si usas ngOnChanges(), te llegarán todos los cambios de todos los inputs a la vez en ngOnChanges(). Con este enfoque, también puedes comparar los valores actual y anterior del input que ha cambiado y actuar en consecuencia.</p><p>Sin embargo, si quieres hacer algo cuando ha cambiado un input en particular &nbsp; (y los otros inputs no te importan), puede ser más sencillo usar un @Input. Sin embargo, este enfoque no te permite &nbsp;comparar valores actuales y anteriores del input que ha cambiado (lo cual es fácil con ngOnChanges).</p><p><strong><strong>EDIT</strong>ADO<strong> 2017–07–25: </strong>LA DETECCIÓN DE CAMBIO DE ANGULAR PUEDE NO DISPARARSE EN ALGUNAS CIRCUNSTANCIAS</strong></p><p>Normalmente, la detección de cambio con @Input y ngOnChanges se dispara cuando el componente padre cambia los datos y los pasa al hijo, <strong>siempre que los datos sean de un tipo primitivo de<strong> JS (string, number, boolean)</strong></strong>. Sin embargo, en los siguientes escenarios, no se disparará y tienes que hacer trabajo extra para que funcione.</p><ol><li>Si estás usando un objeto anidado o un arreglo (en lugar de un tipo primitivo de JS) para pasar los datos del padre al hijo, la detección de cambio (usando @Input o &nbsp;ngOnchanges) puede que no se dispare, como se menciona en la respuesta de muetzerich. Para soluciones mira <a href="https://stackoverflow.com/questions/34796901/angular2-change-detection-ngonchanges-not-firing-for-nested-object" rel="noopener">aquí</a>.</li><li>Si estás mutando datos fuera del contexto de Angular (i.e., externamente), Angular no sabe que ha habido cambios. Tendrías que usar ChangeDetectorRef o NgZone en tu componente para hacer que Angular sepa que ha habido cambios y se dispare la detección de cambios. Mira <a href="https://stackoverflow.com/questions/42971865/angular2-zone-run-vs-changedetectorref-detectchanges" rel="noopener">aquí</a>.</li></ol><p><a href="https://stackoverflow.com/questions/38571812" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="urlarguments">¿Cómo se pasan argumentos url (query string) a una solicitud (request) de HTTP en Angular?</h3><!--kg-card-end: html--><blockquote>154+ votos<em><em>? 1</em></em>57,619+ vistas<br><em><em><a href="https://stackoverflow.com/users/3276721/miguel-lattuada"><strong><strong>Miguel Lattuada</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Hola,estoy creando una solicitud de HTTP en Angular, pero no sé como anadirle argumentos de URL (cadena de consulta (query)).</p><pre><code class="language-ts">this.http.get(StaticSettings.BASE_URL).subscribe(
  (response) =&gt; this.onObtenTiempoResultados(response.json()),
  (error) =&gt; this.onObtenTiempoError(error.json()),
  () =&gt; this.onObtenTiempoCompleto()
);</code></pre><p>Mi StaticSettings.BASE_URL es como una url sin parametros: http://enalgunsitio.com/ pero quiero que sea http://enalgunsitio.com/?var1=val1&amp;var2=val2</p><p>Donde var1, y var2 son parte del objeto de la solicitud de HTTP? Quiero añadirlos como en un objeto.</p><pre><code class="language-json">{
  query: {
    var1: val1,
    var2: val2
  }
}</code></pre><p>y que el módulo de Http haga el trabajo de analizar y descomponer para pasarlo a la cadena de consulta (query) de la URL.</p><blockquote><a href="https://stackoverflow.com/users/5152732" rel="noopener"><strong><strong><em><em>toskv</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (216+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>El método <a href="https://angular.io/api/common/http/HttpClient" rel="noopener"><strong><strong>HttpClient</strong></strong></a> permite configurar <strong><strong>param</strong>s </strong>en sus opciones.</p><p>Puedes configurarlo importando <a href="https://angular.io/api/common/http" rel="noopener"><strong><strong>HttpClientModule</strong></strong></a> del paquete @angular/common/http.</p><pre><code class="language-ts">import {HttpClientModule} from '@angular/common/http';

@NgModule({
  imports: [ BrowserModule, HttpClientModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}</code></pre><p>Luego puedes inyectar <strong><strong>HttpClient</strong></strong> y usarlo en la solicitud.</p><pre><code class="language-ts">import {HttpClient} from '@angular/common/http'</code></pre><pre><code class="language-ts">import {HttpClient} from '@angular/common/http'

@Component({
  selector: 'mi-app',
  template: `
    &lt;div&gt;
      &lt;h2&gt;Hola {{nombre}}&lt;/h2&gt;
    &lt;/div&gt;
  `,
})
export class App {
  nombre:string;
  constructor(private httpClient: HttpClient) {
    this.httpClient.get('/url', {
      params: {
        appid: 'id1234',
        cnt: '5'
      },
      observe: 'response'
    })
    .toPromise()
    .then(response =&gt; {
      console.log(response);
    })
    .catch(console.log);
  }
}</code></pre><p>Tienes un ejemplo <a href="https://plnkr.co/edit/G4mczOLOHfVYKpuaWee3?p=preview" rel="noopener">aquí</a>.</p><p>Para versiones de Angular anteriores a la versión 4 puedes hacer lo mismo con el servicio <strong><strong>Http</strong></strong>.</p><p>El método <strong><strong>Http.get</strong></strong> toma un objeto que implementa RequestOptionsArgs como un segundo parametro.</p><p>El campo <strong><strong>search</strong></strong> de ese objeto se puede usar para poner una cadena o un objeto URLSearchParams.</p><p>Ejemplo:</p><pre><code class="language-ts">// Parameters obj-
 let params: URLSearchParams = new URLSearchParams();
 params.set('appid', StaticSettings.API_KEY);
 params.set('cnt', days.toString());
 
 //Http request-
 return this.http.get(StaticSettings.BASE_URL, {
   search: params
 }).subscribe(
   (response) =&gt; this.onObtenTiempoResultado(response.json()), 
   (error) =&gt; this.onObtenerTIempoError(error.json()), 
   () =&gt; this.onObtenerTiempoCompleto()
 );</code></pre><p><a href="https://stackoverflow.com/questions/34475523" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="deployangular">¿Cómo se despliegan las aplicaciones de Angular?</h3><!--kg-card-end: html--><blockquote>153+ votos<em><em>? 8</em></em>9,991+ vistas<br><em><em><a href="https://stackoverflow.com/users/1362355/joseph-girgis"><strong><strong>Joseph Assem Sobhy</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>¿Cómo se despliegan las aplicaciones de Angular para producción?</p><p>Todas las guías que he visto hasta ahora &nbsp;cuentan con un servidor lite-server para servir y browserSync para reflejar los cambios — pero cuando acabas con el desarrollo ,¿Cómo se publica la aplicación?</p><p>Importo todos los ficheros <code>.js</code> compilados en <code>index.html</code> o los "minify" con gulp? ¿funcionará? ¿Necesito SystemJS en la versión de producción?</p><blockquote><a href="https://stackoverflow.com/users/1035889" rel="noopener"><strong><strong><em><em>Amid</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (74+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Estás haciendo dos preguntas a la vez. La primera es como alojar tu aplicación. Y como dice @toskv es una pregunta demasiado amplia como para poderla contestar y depende de muchas cosas. La segunda es más especifica — cómo preparas la versión para el despliegue . Tienes varias opciones:</p><ol><li>Despliegala tal cual está. No minificación, concatenación, cambios de nombres etc. Transcompila todo tu proyecto, copia todos los js/css/… resultantes + dependencias al servidor que alojará tu aplicación y ya lo tienes.</li><li>Despliega usando herramientas especificas. Como webpack o systemjs builder. Incluyen todas las posibilidades que faltan en #1. Puedes empaquetar todo tu código en un par de ficheros js/css/… a los que haces referencia en tu HTML. Systemjs buider incluso te permite no tener que incluir systemjs como parte del paquete de despliegue.</li></ol><p>Sí, lo más probable es que necesites implementar systemjs y muchas otras libraries externas como parte de tu paquete. Y sí que podrás ponerlas en un par de ficheros js a los que hagas referencia en tu HTML. No tienes que referenciar todos tus ficheros js compilados desde la página — systemjs como cargador de módulos se encarga de eso.</p><p>Sé que suena lioso— para ayudarte a comenzar con #2 aquí van dos ejemplos sencillos:</p><p>SystemJS builder: <a href="https://github.com/mgechev/angular2-seed" rel="noopener">angular2 seed</a></p><p>WebPack: <a href="https://github.com/AngularClass/angular2-webpack-starter" rel="noopener">angular2 webpack starter</a></p><p>Mira como lo hacen — y, con suerte, esto te ayudará a encontrar la forma de agrupar las aplicaciones que crees.</p><p><a href="https://stackoverflow.com/questions/35539622" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="ngforwithindex">ngFor con index como un atributo con un valor</h3><!--kg-card-end: html--><blockquote>149+ votos <em><em>? 1</em></em>95,294+ vistas<br><em><em><a href="https://stackoverflow.com/users/1175327/vivendi"><strong><strong>Vivendi</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Tengo un bucle <code>ngFor</code> sencillo que realiza un seguimiento &nbsp;<code>index</code> actual. Quiero guardar el valor de ese <code>index</code> en un atributo para poder imprimirlo. Pero no sé como se hace.</p><p>Tengo esto:</p><pre><code class="language-ts">&lt;ul *ngFor="#elemento of elementos; #i = index" data-index="#i"&gt;
    &lt;li&gt;{{elemento}}&lt;/li&gt;
&lt;/ul&gt;</code></pre><p>Quiero guardar el valor <code>#i</code> en el atributo <code>data-index</code>. He probado varias formas pero ninguna me funciona.</p><p>Tengo una demo aquí: <a href="http://plnkr.co/edit/EXpOKAEIFlI9QwuRcZqp?p=preview" rel="noopener">http://plnkr.co/edit/EXpOKAEIFlI9QwuRcZqp?p=preview</a></p><p>¿Cómo puedo almacenar el valor de <code>index</code> en el atributo <code>data-index</code> ?</p><blockquote><a href="https://stackoverflow.com/users/1873365" rel="noopener"><strong><strong><em><em>Thierry Templier</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (284+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Yo usaría esta sintaxis para establecer el valor del índice en un atributo del elemento HTML:</p><pre><code class="language-ts">&lt;ul&gt;
    &lt;li *ngFor="#elemento of elementos; #i = index" [attr.data-index]="i"&gt;
        {{elemento}}
    &lt;/li&gt;
&lt;/ul&gt;</code></pre><p>Aquí está el ejemplo con los cambios: <a href="http://plnkr.co/edit/LiCeyKGUapS5JKkRWnUJ?p=preview" rel="noopener">http://plnkr.co/edit/LiCeyKGUapS5JKkRWnUJ?p=preview</a>.</p><p><strong>Actualizado para los lanzamientos de <strong>angular 2</strong></strong> Debes usar <code>let</code> en lugar de &nbsp;<code>#</code>.</p><pre><code class="language-ts">&lt;ul&gt;
    &lt;li *ngFor="let elemento of elementos; let i = index" [attr.data-index]="i"&gt;
        {{item}}
    &lt;/li&gt;
&lt;/ul&gt;</code></pre><p><a href="https://stackoverflow.com/questions/35405618" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="globalconstants">Define constantes globales en Angular 2</h3><!--kg-card-end: html--><blockquote>149+ votos<em><em>? 1</em></em>28,101+ vistas<br><em><em><a href="https://stackoverflow.com/users/2946773/andrefeijo"><strong><strong>AndreFeijo</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>En Angular 1.x puedes definir constantes así:</p><pre><code class="language-ts">angular.module('mainApp.config', [])
.constant('API_ENDPOINT', 'http://127.0.0.1:6666/api/')</code></pre><p>¿Cuál sería el equivalente en Angular2 (con Typescript)? No quiero repetir la url base de la API una y otra vez en mis servicios.</p><blockquote><a href="https://stackoverflow.com/users/2946773" rel="noopener"><strong><strong><em><em>AndreFeijo</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (159+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong>Estos cambios a mi me funcionan en la versión final de <strong>Angular 2:</strong></strong></p><pre><code class="language-ts">export class AppSettings {
   public static API_ENDPOINT='http://127.0.0.1:6666/api/';
}</code></pre><p><strong>Y en el servicio<strong>:</strong></strong></p><pre><code class="language-ts">import {Http} from 'angular2/http';
import {Message} from '../models/message';
import {Injectable} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {AppSettings} from '../appSettings';
import 'rxjs/add/operator/map';

@Injectable()
export class MensajeServicio {

    constructor(private http: Http) { }
    
    obtenerMensajes(): Observable&lt;Message[]&gt; {
        return this.http.get(AppSettings.API_ENDPOINT+'/messages')
            .map(response =&gt; response.json())
            .map((messages: Object[]) =&gt; {
                return messages.map(message =&gt; this.parseData(message));
            });
    }
    
    private parseData(data): Message {
        return new Message(data);
    }
}</code></pre><p><a href="https://stackoverflow.com/questions/34986922" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="pipesservicescomponents">Angular — Usar pipes en servicios y componentes</h3><!--kg-card-end: html--><blockquote>148+ votos<em><em>? 7</em></em>5,716+ vistas<br><em><em><a href="https://stackoverflow.com/users/4602586/posix-compliant"><strong><strong>POSIX-compliant</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>En AngularJS, puedo usar filtros (pipes) dentro de los servicios y controllers usando algo como esto:</p><pre><code class="language-ts">$filter('date')(miFecha, 'yyyy-MM-dd');</code></pre><p>¿se puede hacer lo mismo en Angular?</p><blockquote><a href="https://stackoverflow.com/users/971121" rel="noopener"><strong><strong><em><em>cexbrayat</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (271+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Como siempre, en Angular, puedes confiar en la inyección de dependencia:</p><pre><code class="language-ts">import { DatePipe } from '@angular/common';
class MiServicio {

  constructor(private fechaPipe: DatePipe) {}
  
  transformaFecha(fecha) {
    this.fechaPipe.transform(miFecha, 'yyyy-MM-dd');
  }
}</code></pre><p>Añade <code>DatePipe</code> a tu lista de proveedores en tu módulo; Si se te olvida te da un error &nbsp;<code>no provider for DatePipe</code>:</p><pre><code>providers: [DatePipe,...]</code></pre><p>Ten en cuenta que &nbsp;<code>DatePipe</code> dependía de la Intl API hasta la versión 5, que no es compatible con todos los navegadores (comprueba la <a href="http://kangax.github.io/compat-table/esintl/" rel="noopener">compatibilidad</a>).</p><p>Si estás usando una versión de Angular más antigua, debes añadir &nbsp;<code>Intl</code> polyfill a tu proyecto para evitar problemas. </p><p><a href="https://stackoverflow.com/questions/35144821" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="cantbindrouterlink">Excepción en Angular2: Can’t bind to ‘routerLink’ since it isn’t a known native property (No se puede enlazar con 'routerLink' porque no es una propiedad  nativa conocida.</h3><!--kg-card-end: html--><blockquote>144+ votos<em><em>? 8</em></em>3,326+ vistas<br><em><em><a href="https://stackoverflow.com/users/1798547/lester-burnham"><strong><strong>Lester Burnham</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Obviamente la versión beta de Angular2 es muy nueva, así que no hay mucha información disponible, pero estoy intentando hacer algo que yo creo es básico en enrutamiento (routing).</p><p>Hackeando con el código de inicio rápido y otros fragmentos de la página de <a href="https://angular.io/" rel="noopener">https://angular.io</a> he hecho esta estructura:</p><pre><code>angular-testapp/
    app/
        app.component.ts
        boot.ts
        routing-test.component.ts
    index.html</code></pre><p>Con los ficheros así:</p><p><strong><strong>index.html</strong></strong></p><pre><code class="language-html">&lt;html&gt;

  &lt;head&gt;
    &lt;base href="/"&gt;
    &lt;title&gt;Angular 2 QuickStart&lt;/title&gt;
    &lt;link href="../css/bootstrap.css" rel="stylesheet"&gt;
    
    &lt;!-- 1. cargar librerias - libraries --&gt;
    &lt;script src="node_modules/angular2/bundles/angular2-polyfills.js"&gt;&lt;/script&gt;
    &lt;script src="node_modules/systemjs/dist/system.src.js"&gt;&lt;/script&gt;
    &lt;script src="node_modules/rxjs/bundles/Rx.js"&gt;&lt;/script&gt;
    &lt;script src="node_modules/angular2/bundles/angular2.dev.js"&gt;&lt;/script&gt;
    &lt;script src="node_modules/angular2/bundles/router.dev.js"&gt;&lt;/script&gt;
    
    &lt;!-- 2. Configurar SystemJS --&gt;
    &lt;script&gt;
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/boot')
            .then(null, console.error.bind(console));
    &lt;/script&gt;
    
  &lt;/head&gt;
  
  &lt;!-- 3. Mostrar la aplicacion --&gt;
  &lt;body&gt;
    &lt;my-app&gt;Cargando...&lt;/my-app&gt;
  &lt;/body&gt;
  
&lt;/html&gt;</code></pre><p><strong><strong>boot.ts</strong></strong></p><pre><code class="language-ts">import {bootstrap}    from 'angular2/platform/browser'
import {ROUTER_PROVIDERS} from 'angular2/router';

import {AppComponent} from './app.component'

bootstrap(AppComponent, [
    ROUTER_PROVIDERS
]);</code></pre><p><strong><strong>app.component.ts</strong></strong></p><pre><code class="language-ts">import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, LocationStrategy, HashLocationStrategy} from 'angular2/router';

import {RoutingTestComponent} from './routing-test.component';

@Component({
    selector: 'mi-app',
    template: `
        &lt;h1&gt;Componente Router&lt;/h1&gt;
        &lt;a [routerLink]="['RoutingTest']"&gt;Test de enrutamiento/Routing&lt;/a&gt;
        &lt;router-outlet&gt;&lt;/router-outlet&gt;
        `
})

@RouteConfig([
    {path:'/routing-test', name: 'RoutingTest', component: RoutingTestComponent, useAsDefault: true},
])

export class AppComponent { }</code></pre><p><strong><strong>routing-test.component.ts</strong></strong></p><pre><code class="language-ts">import {Component} from 'angular2/core';
import {Router} from 'angular2/router';

@Component({
    template: `
        &lt;h2&gt;Test de enrutamiento/routing&lt;/h2&gt;
        &lt;p&gt;Algo interesante aquí!&lt;/p&gt;
        `
})
export class RoutingTestComponent { }</code></pre><p>Pero cuando intento correr la aplicación me da:</p><pre><code class="language-bash">EXCEPTION: Template parse errors:
Can't bind to 'routerLink' since it isn't a known native property ("
        &lt;h1&gt;Componente Router&lt;/h1&gt;
        &lt;a [ERROR -&gt;][routerLink]="['RoutingTest']"&gt;Test de enrutamiento&lt;/a&gt;
        &lt;router-outlet&gt;&lt;/router-outlet&gt;
        "): AppComponent@2:11</code></pre><p>He encontrado un problema parecido; <a href="https://stackoverflow.com/questions/34304115/router-link-directives-broken-after-upgrading-to-angular2-0-0-beta-0" rel="noopener">router-link directives broken after upgrading to angular2.0.0-beta.0</a>. Pero, el “ejemplo que funciona” en una de las respuestas basadas en código pre-beta —que bien puede funcionar, pero me gustaría saber por qué el código que he creado no funciona.</p><p>¡Cualquier sugerencia sería recibida con gratitud!</p><blockquote><a href="https://stackoverflow.com/users/217408" rel="noopener"><strong><strong><em><em>Günter Zöchbauer</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (220+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong><strong>&gt;=R</strong></strong>C.5</p><p>Importa <code>RouterModule</code> </p><pre><code class="language-ts">@NgModule({ 
  imports: [RouterModule],
  ...
})</code></pre><p><strong><strong>&gt;=R</strong></strong>C.2</p><p><strong><strong>app.routes.ts</strong></strong></p><pre><code class="language-ts">import { provideRouter, RouterConfig } from '@angular/router';

export const routes: RouterConfig = [
  ...
];

export const APP_ROUTER_PROVIDERS = [provideRouter(routes)];</code></pre><p><strong><strong>main.ts</strong></strong></p><pre><code>import { bootstrap } from '@angular/platform-browser-dynamic';
import { APP_ROUTER_PROVIDERS } from './app.routes';

bootstrap(AppComponent, [APP_ROUTER_PROVIDERS]);</code></pre><p><strong><strong>&lt;=RC.1</strong></strong></p><p>A tu código le falta</p><pre><code class="language-ts">@Component({
    ...
    directives: [ROUTER_DIRECTIVES],
    ...)}</code></pre><p>No puedes usar directives como <code>routerLink</code> o <code>router-outlet</code> sin darlas a conocer a tu componente.</p><p>Aunque los nombres de las directives se cambiaron para distinguir entre mayúsculas y minúsculas en Angular2, los elementos siguen usando <code>-</code> en el nombre, como <code>&lt;router-outlet&gt;</code> para ser compatibles con las especificaciones de componentes web que requieren un - en el nombre de elementos personalizados.</p><p><strong>Registra globalmente</strong></p><p>Para que <code>ROUTER_DIRECTIVES</code> este disponible globalmente, añade este provider a <code>bootstrap(...)</code>:</p><pre><code>provide(PLATFORM_DIRECTIVES, {useValue: [ROUTER_DIRECTIVES], multi: true})</code></pre><p>Entonces ya no necesitas añadir <code>ROUTER_DIRECTIVES</code> a cada componente.</p><p><a href="https://stackoverflow.com/questions/34317044" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="dynamictabs">Angular: 2 pestañas dinámicas con componentes seleccionados por el usuario por click.</h3><!--kg-card-end: html--><blockquote>143+ votos<em><em>? 8</em></em>0,735+ vistas<br><em><em><a href="https://stackoverflow.com/users/2951897/cuel"><strong><strong>Cuel</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy intentando configurar un sistema de pestañas que permita a componentes registrarse a sí mismos (con un título). La primera pertaña es como una bandeja de entrada, hay muchos elementos de acciones/enlaces, y cada uno de estos clicks debe instanciar un componente nuevo, en el click. Las acciones / enlaces vienen de JSON.</p><p>El componente instanciado se registrará a si mismo como una nueva pestaña.</p><p>No sé si esta es la mejor manera de hacer esto. Por ahora las guías que he visto son para pestañas estáticas, lo cual no ayuda.</p><p>Por ahora solamente tengo el servicio para las pestañas que está en main para persistir por toda la app, es más o menos como esto.</p><pre><code class="language-ts">export interface ITab { titulo: string; }

@Injectable()
export class PestanaServicio {
    private pestanas = new Set&lt;ITab&gt;();
    
    anadirPestana(titulo: string): ITab {
        let pestana: ITab = { titulo };
        this.pestanas.add(pestana);
        return pestana;
    }
    
    quitarPestana(pestana: ITab) {
        this.pestanas.delete(pestana);
    }
}</code></pre><p>Preguntas:</p><p>1)¿Cómo puedo tener una lista dinámica en la bandeja de entrada que cree nuevas pestañas (diferentes)? Me imagino que con DynamicComponentBuilder?</p><p>2) ¿Cómo pueden los componentes creados desde la bandeja de entrada (al hacer clic) registrarse como pestañas y también mostrarse? Supongo que con ng-content pero no puedo encontrar mucha información al respecto.</p><p>Editado: Para aclarar</p><p>Piensa en la bandeja de entrada como una bandeja de entrada de correo, los elementos se sacan de JSON y muestran varios elementos. Una vez que se hace clic en uno de los elementos, se crea una nueva pestaña con ‘type’. El tipo (type) es un componente.</p><p>Editado2: Image</p><p><a href="http://i.imgur.com/yzfMOXJ.png" rel="noopener">http://i.imgur.com/yzfMOXJ.png</a></p><blockquote><a href="https://stackoverflow.com/users/217408" rel="noopener"><strong><strong><em><em>Günter Zöchbauer</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (190+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong>actualizado</strong></p><p><strong>ejemplo: <a href="https://stackblitz.com/edit/angular-ygz3jg"><strong>Angular 5 StackBlitz</strong></a></strong></p><p><strong>actualizado</strong></p><p><code>ngComponentOutlet</code> se añadio a 4.0.0-beta.3</p><p><strong>actualizado</strong></p><p>Hay un <code>NgComponentOutlet</code> que se está creando que hace algo similar <a href="https://github.com/angular/angular/pull/11235" rel="noopener">https://github.com/angular/angular/pull/11235</a></p><p><strong><strong>RC.7</strong></strong></p><p><strong><a href="http://plnkr.co/edit/UGzoPTCHlXKWrn4p8gd1?p=preview">Ejemplo <strong>Plunker RC.7</strong></a></strong></p><pre><code class="language-ts">// componente de ayuda para anadir nuevos componentes
@Component({
  selector: 'dcl-wrapper',
  template: `&lt;div #target&gt;&lt;/div&gt;`
})
export class DclWrapper {
  @ViewChild('target', {read: ViewContainerRef}) target: ViewContainerRef;
  @Input() tipo: Type&lt;Component&gt;;
  cmpRef: ComponentRef&lt;Component&gt;;
  private estaLaVistaInicializada:boolean = false;
  
  constructor(private componentFactoryResolver: ComponentFactoryResolver, private compiler: Compiler) {}
  
  actualizarComponente() {
    if(!this.estaLaVistaInicializada) {
      return;
    }
    if(this.cmpRef) {
      // cuando el `tipo` del input cambia destruimos uno
      //creado previamente antes de crear el nuevo     
      this.cmpRef.destroy();
    }
    
    let factory = this.componentFactoryResolver.resolveComponentFactory(this.tipo);
    this.cmpRef = this.target.createComponent(factory)
    // para acceder a la instancia creada
    // this.compRef.instance.unaPropiedad = 'unValor';
    // this.compRef.instance.unOutput.subscribe(val =&gt; hazAlgo());
  }
  
  ngOnChanges() {
    this.actualizarComponente();
  }
  
  ngAfterViewInit() {
    this.estaLaVistaInicializada = true;
    this.actualizarComponente();  
  }
  
  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }    
  }
}</code></pre><p>ejemplo de uso</p><pre><code class="language-ts">// Usq dcl-wrapper component
@Component({
  selector: 'mis-pestanas',
  template: `
  &lt;h2&gt;pestanas&lt;/h2&gt;
  &lt;div *ngFor="let pestana of pestanas"&gt;
    &lt;dcl-wrapper [type]="tab"&gt;&lt;/dcl-wrapper&gt;
  &lt;/div&gt;
`
})
export class Pestanas {
  @Input() pestanas;
}

@Component({
  selector: 'mi-app',
  template: `
  &lt;h2&gt;Hola {{nombre}}&lt;/h2&gt;
  &lt;mis-pestanas [pestanas]="tipos"&gt;&lt;/mis-pestanas&gt;
`
})
export class App {
  //la lista usada para crear las pestanas
  tipos = [C3, C1, C2, C3, C3, C1, C1];
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, DclWrapper, Tabs, C1, C2, C3],
  entryComponents: [C1, C2, C3],
  bootstrap: [ App ]
})
export class AppModule {}</code></pre><p><strong>versiones anteriores</strong></p><p><strong><strong>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</strong></strong></p><p>Esto cambio en Angular2 RC.5</p><p>Actualizaré el ejemplo de abajo pero es mi último día antes de las vacaciones.</p><p>Este ejemplo de <a href="http://plnkr.co/edit/3dzkMVXe4AGSRhk11TXG?p=preview" rel="noopener">Plunker</a> demuestra como crear componentes de forma dinámica en RC.5</p><p><strong>Actualizado<strong>— us</strong>a<strong> <a href="https://angular.io/docs/ts/latest/api/core/index/ViewContainerRef-class.html" rel="noopener">ViewContainerRef</a>.createComponent()</strong></strong></p><p>Como <code>DynamicComponentLoader</code> es obsoleto, El enfoque se debe actualizar nuevamente.</p><pre><code class="language-ts">@Component({
  selector: 'dcl-wrapper',
  template: `&lt;div #target&gt;&lt;/div&gt;`
})
export class DclWrapper {
  @ViewChild('target', {read: ViewContainerRef}) target;
  @Input() tipo;
  cmpRef:ComponentRef;
  private estaVistaInicializada:boolean = false;
  
  constructor(private resolver: ComponentResolver) {}
  
  actualizaComponente() {
    if(!this.estaVistaInicializada) {
      return;
    }
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
   this.resolver.resolveComponent(this.tipo).then((factory:ComponentFactory&lt;any&gt;) =&gt; {
      this.cmpRef = this.target.createComponent(factory)
      // para acceder a la instancia creada
      // this.compRef.instance.unaPropiedad = 'unValor';
      // this.compRef.instance.unOutput.subscribe(val =&gt; hazAlgo());
    });
  }
  
  ngOnChanges() {
    this.actualizaComponente();
  }
  
  ngAfterViewInit() {
    this.estaVistaInicializada = true;
    this.actualizaComponente();  
  }
  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }    
  }
}</code></pre><p><strong><a href="http://plnkr.co/edit/GJTLrnQdRDBvZenX59PZ?p=preview"><strong>Plunker </strong>ejemplo<strong> RC.4</strong></a></strong><br><strong><a href="https://plnkr.co/edit/PpgMvS?p=preview"><strong>Plunker e</strong>jemplo<strong> beta.17</strong></a></strong></p><p><strong>Actualizado<strong>— us</strong>a<strong> loadNextToLocation</strong></strong></p><pre><code class="language-ts">export class DclWrapper {
  @ViewChild('target', {read: ViewContainerRef}) target;
  @Input() tipo;
  cmpRef:ComponentRef;
  private estaVistaInicializada:boolean = false;
  
  constructor(private dcl:DynamicComponentLoader) {}
  
  actualizaComponente() {
    // ejecuta cada vez que `tipo` cambia pero no antes de la llamada a  `//ngAfterViewInit()` se realiza 
    // para inicializar un `target` 
    if(!this.estaVistaInicializada) {
      return;
    }
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
    this.dcl.loadNextToLocation(this.tipo, this.target).then((cmpRef) =&gt; {
      this.cmpRef = cmpRef;
    });
  }
  
  ngOnChanges() {
    this.actualizaComponente();
  }
  
  ngAfterViewInit() {
    this.estaVistaInicializada = true;
    this.actualizaComponente();  
  }
  
  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }    
  }
}</code></pre><p><strong><a href="https://plnkr.co/edit/kc2Bgg?p=preview"><strong>Plunker </strong>ejemplo <strong>beta.17</strong></a></strong></p><p><strong><strong>original</strong></strong></p><p>No entiendo muy bien lo que necesitas pero creo que puede ser esto.</p><p>El componente <code>Pestanas</code> toma un arreglo de tipos (types) y crea pestañas (tabs) para cada elemento del arreglo.</p><pre><code class="language-ts">@Component({
  selector: 'dcl-wrapper',
  template: `&lt;div #target&gt;&lt;/div&gt;`
})
export class DclWrapper {
  constructor(private elRef:ElementRef, private dcl:DynamicComponentLoader) {}
  @Input() tipo;
  
  ngOnChanges() {
    if(this.cmpRef) {
      this.cmpRef.dispose();
    }
    this.dcl.loadIntoLocation(this.tipo, this.elRef, 'target').then((cmpRef) =&gt; {
      this.cmpRef = cmpRef;
    });
  }
}

@Component({
  selector: 'c1',
  template: `&lt;h2&gt;c1&lt;/h2&gt;`
  
})
export class C1 {
}

@Component({
  selector: 'c2',
  template: `&lt;h2&gt;c2&lt;/h2&gt;`
})
export class C2 {
}
@Component({
  selector: 'c3',
  template: `&lt;h2&gt;c3&lt;/h2&gt;`
  
})
export class C3 {
}

@Component({
  selector: 'mis-pestanas',
  directives: [DclWrapper],
  template: `
  &lt;h2&gt;Pestanas&lt;/h2&gt;
  &lt;div *ngFor="let pestana of pestanas"&gt;
    &lt;dcl-wrapper [tipo]="pestana"&gt;&lt;/dcl-wrapper&gt;
  &lt;/div&gt;
`
})
export class Pestanas {
  @Input() pestanas;
}

@Component({
  selector: 'mi-app',
  directives: [Pestanas]
  template: `
  &lt;h2&gt;Hola {{nombre}}&lt;/h2&gt;
  &lt;mis-pestanas [pestanas]="tipos"&gt;&lt;/mis-pestanas&gt;
`
})
export class App {
  types = [C3, C1, C2, C3, C3, C1, C1];
}</code></pre><p><strong><a href="https://plnkr.co/edit/kc2Bgg?p=preview"><strong>Plunker </strong>ejemplo<strong> beta.15</strong></a></strong> (no está basado en tu Plunker)</p><p>También hay una forma de pasar datos al componente creado dinámicamente como (<code>unosDatos</code> pasados como <code>tipo</code>)</p><pre><code class="language-ts">this.dcl.loadIntoLocation(this.tipo, this.elRef, 'target').then((cmpRef) =&gt; {
  cmpRef.instance.unaPropiedad = unosDatos;
  this.cmpRef = cmpRef;
});</code></pre><p>También hay algo de soporte para usar la inyección de dependencia con servicios compartidos.</p><p><a href="https://stackoverflow.com/questions/36325212" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="eventemitterobservable">Delegación: EventEmitter o Observable en Angular</h3><!--kg-card-end: html--><blockquote>141+ votos<em><em>? 7</em></em>8,505+ vistas<br><em><em><a href="https://stackoverflow.com/users/1066899/the-critic"><strong><strong>the_critic</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy tratando de implementar algo así como un patrón de delegación en Angular. Cuando el usuario hace click en <code>nav-item</code>, me gustaría llamar a una función que luego emita un evento que a su vez debe ser ser tratado por algún otro componente que está escuchando el evento.</p><p>El escenario: Tengo un componente <code>Navigation</code>:</p><pre><code class="language-ts">import {Component, Output, EventEmitter} from 'angular2/core';

@Component({
    // otras propiedades que no incluyo
    events : ['navchange'], 
    template:`
      &lt;div class="nav-item" (click)="elementoNavSeleccionado(1)"&gt;&lt;/div&gt;
    `
})

export class Navigation {

    @Output() navchange: EventEmitter&lt;number&gt; = new EventEmitter();
    
    elementoNavSeleccionado(elem: number) {
        console.log('elemento nav seleccionado ' + elem);
        this.navchange.emit(elem)
    }
    
}</code></pre><p>El componente que observa:</p><pre><code class="language-ts">export class ObservadorComponent {

  // como observo ? 
  // &lt;----------evento observe/register ?--------&gt;
  
  public elementoNavSeleccionado(elem: number) {
    console.log('index del elemento cambiado!');
  }
  
}</code></pre><p>La pregunta es, ¿Cómo hago que el componente observe el evento en cuestión?</p><blockquote><a href="https://stackoverflow.com/users/215945" rel="noopener"><strong><strong><em><em>Mark Rajcok</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (306+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p><strong>Actualizado <strong>2016–06–27:</strong></strong> En lugar de usar Observables, usa uno de esto dos:</p><ul><li>un BehaviorSubject, recomendado por @Abdulrahman en un comentario, o</li><li>un ReplaySubject, recomendado por @Jason Goemaat en un comentario</li></ul><p>Un Subject es un Observable (así que nos podemos suscribir( <code>subscribe()</code> ) a él) y un observador (Observer) (así que podemos usar &nbsp;<code>next()</code> para emitir un valor nuevo). Explotamos esta característica. Un Subject permite que los valores notifiquen a muchos observadores (Observers). No explotamos esta propiedad (solamente tenemos un Observer).</p><p><a href="http://reactivex.io/rxjs/manual/overview.html#behaviorsubject" rel="noopener">BehaviorSubject</a> es una variante de Subject. Tiene noción del "valor actual". Explotamos esto: cuando creamos un ObservingComponent, obtiene el valor del elemento de navegación actual de BehaviorSubject automáticamente.</p><p>El código más abajo y en <a href="http://plnkr.co/edit/XqwwUM44NQEpxQVFFxNW?p=preview" rel="noopener">plunker</a> usan BehaviorSubject.</p><p><a href="http://reactivex.io/rxjs/manual/overview.html#replaysubject" rel="noopener">ReplaySubject</a> es otra variante de Subject. Si quieres esperar a que un valor sea producido, usa <code>ReplaySubject(1)</code>. Mientras que BehaviorSubject requiere un valor inicial (que se proporcionará de inmediato), ReplaySubject no lo require. ReplaySubject siempre proporcionará el valor más reciente, pero como no require un valor inicial, el servicio puede hacer operaciones asíncronas antes de devolver su primer valor. Igualmente se disparará inmediatamente en llamadas posteriores con el valor más reciente. Si solamente quieres un valor, usa <code>first()</code> en la suscripción. Si usas <code>first()</code> no necesitas borrar la suscripción (unsubscribe).</p><pre><code class="language-ts">import {Injectable}      from '@angular/core'
import {BehaviorSubject} from 'rxjs/BehaviorSubject';

@Injectable()
export class NavService {
  // elemento de navegacion Observable 
  private _navItemSource = new BehaviorSubject&lt;number&gt;(0);
  // elemento de navegacion observable - flujo
  navItem$ = this._navItemSource.asObservable();
  // comando de servicio
  changeNav(number) {
    this._navItemSource.next(number);
  }
}

import {Component}    from '@angular/core';
import {NavService}   from './nav.service';
import {Subscription} from 'rxjs/Subscription';

@Component({
  selector: 'obs-comp',
  template: `obs component, item: {{item}}`
})
export class ObservadorComponent {
  item: number;
  subscription:Subscription;
  constructor(private _navService:NavService) {}
  ngOnInit() {
    this.subscription = this._navService.navItem$
       .subscribe(item =&gt; this.item = item)
  }
  ngOnDestroy() {
    // evitar la fuga de memoria cuando se destruye el componente
    this.subscription.unsubscribe();
  }
}

@Component({
  selector: 'mi-nav',
  template:`
    &lt;div class="nav-item" (click)="SeleccionadoNavItem(1)"&gt;nav 1 (clickeame)&lt;/div&gt;
    &lt;div class="nav-item" (click)="SeleccionadoNavItem(2)"&gt;nav 2 (clickeame)&lt;/div&gt;`
})
export class Navigation {
  item = 1;
  constructor(private _navService:NavService) {}
  SeleccionadoNavItem(item: number) {
    console.log('elemento de nav seleccionado' + item);
    this._navService.changeNav(item);
  }
}</code></pre><p><a href="http://plnkr.co/edit/XqwwUM44NQEpxQVFFxNW?p=preview" rel="noopener">Plunker</a></p><p><strong>Respuesta <strong>Original </strong>que usa un<strong> Observable:</strong></strong> (require más lógica y código que BehaviorSubject, así que no lo recomiendo pero puede ser instructivo)</p><p>Esta implementación usa Observable en lugar de <a href="https://stackoverflow.com/a/34402436/215945" rel="noopener">EventEmitter</a>. A diferencia de mi implementacuión con EventEmitter, esta implementación también guarda el valor seleccionado actualmente ( <code>navItem</code> ) en el servicio, de modo que cuando se crea un componente de observación, puede recuperar el valor actual a través de una llamada API &nbsp;<code>navItem()</code>, y es notificado de cambios con la Observable ( <code>navChange$</code>).</p><pre><code class="language-ts">import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/share';
import {Observer} from 'rxjs/Observer';

export class NavService {
  private _navItem = 0;
  navChange$: Observable&lt;number&gt;;
  private _observer: Observer;
  constructor() {
    this.navChange$ = new Observable(observer =&gt;
      this._observer = observer).share();
    // share() permite varios suscriptores
  }
  changeNav(number) {
    this._navItem = number;
    this._observer.next(number);
  }
  navItem() {
    return this._navItem;
  }
}

@Component({
  selector: 'obs-comp',
  template: `obs component, item: {{item}}`
})
export class ObservadorgComponent {
  item: number;
  subscription: any;
  constructor(private _navService:NavService) {}
  ngOnInit() {
    this.item = this._navService.navItem();
    this.subscription = this._navService.navChange$.subscribe(
      item =&gt; this.elementoNavSeleccionado(item));
  }
  elementoNavSeleccionado(item: number) {
    this.item = item;
  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

@Component({
  selector: 'mi-nav',
  template:`
    &lt;div class="nav-item" (click)="elementoNavSeleccionado(1)"&gt;nav 1 (click me)&lt;/div&gt;
    &lt;div class="nav-item" (click)="elementoNavSeleccionado(2)"&gt;nav 2 (click me)&lt;/div&gt;
  `,
})
export class Navigation {
  item:number;
  constructor(private _navService:NavService) {}
  elementoNavSeleccionado(item: number) {
    console.log('elemento nav seleccionado ' + item);
    this._navService.changeNav(item);
  }
}</code></pre><p><a href="http://plnkr.co/edit/vL76b0UjrAav3Ao7kF4W?p=preview" rel="noopener">Plunker</a></p><p><a href="https://stackoverflow.com/questions/34376854" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="bootstrapangular">¿Cómo se añade bootstrap a un proyecto angular-cli?</h3><!--kg-card-end: html--><blockquote>140+ votos<em><em>? 1</em></em>66,741+ vistas<br><em><em><a href="https://stackoverflow.com/users/811865/jerome"><strong><strong>Jerome</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Queremos usar bootstrap 4 (4.0.0-alpha.2) en nuestra app generada con angular-cli 1.0.0-beta.5 (w/ node v6.1.0).</p><p>Después de obtener bootstrap y sus dependencias con npm, nuestro primer intento consistió en agregarlos en <code>angular-cli-build.js</code>:</p><pre><code class="language-js">'bootstrap/dist/**/*.min.+(js|css)',  
  'jquery/dist/jquery.min.+(js|map)',  
  'tether/dist/**/*.min.+(js|css)',</code></pre><p>e importarlos en <code>index.html</code></p><pre><code class="language-html">&lt;script src="vendor/jquery/dist/jquery.min.js"&gt;&lt;/script&gt;
  &lt;script src="vendor/tether/dist/js/tether.min.js"&gt;&lt;/script&gt;
  &lt;link rel="stylesheet" type="text/css" href="vendor/bootstrap/dist/css/bootstrap.min.css"&gt;
  &lt;script src="vendor/bootstrap/dist/js/bootstrap.min.js"&gt;&lt;/script&gt;</code></pre><p>Esto funcionaba con <code>ng serve</code> pero en cuanto creamos la compilación (build) con <code>-prod</code> &nbsp;<code>dist/vendor</code> todas las dependencias desaparecierón(sorpresa !).</p><p><strong>¿Cómo debemos tratar tal escenario? (i.e. cargando los scripts de bootstrap en un proyecto generado con <strong>angular-cli ?</strong></strong></p><p>Habiamos pensado esto pero no sabemos bien por donde tirar…</p><ul><li>¿usar un CDN ? pero preferimos servir estos archivos para garantizar que estarán disponibles</li><li>¿copiar dependencias a <code>dist/vendor</code> despues de nuestro <code>ng build -prod</code> ? ¿Pero eso parece algo que angular-cli debería proporcionar ya que 'se ocupa' de la parte de compilación?</li><li>¿añadir jquery, bootstrap y tether en src/system-config.ts y de alguna manera ponerlos en el paquete main.ts ? Pero eso parecía incorrecto considerando que no los vamos a usar explícitamente en el código de nuestra aplicación. (a diferencia de moment.js o algo como lodash, por ejemplo)</li></ul><blockquote><a href="https://stackoverflow.com/users/1417742" rel="noopener"><strong><strong><em><em>pd farhad</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (202+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>**ACTUALIZACIÓN &nbsp;IMPORTANTE: ng2-bootstrap ahora es <a href="https://github.com/valor-software/ngx-bootstrap" rel="noopener">ngx-bootstrap</a> **</p><p>ngx-bootstrap funciona con angular 3 y 4.</p><p><strong>Actualizado<strong> :</strong></strong> <code><strong><strong>1.0.0-beta.11-webpack</strong></strong></code><strong><strong> o </strong>posteriores</strong></p><p>Primero compruebla tu versión de angular-cli con el siguiente comando en la terminal: <code>ng -v</code></p><p>Si la versión es posterior a &nbsp;<code>1.0.0-beta.11-webpack</code> sigue estos pasos:</p><ol><li>instala <strong><strong>ngx-bootstrap</strong></strong> y <strong><strong>bootstrap:</strong></strong><br><code>npm install ngx-bootstrap bootstrap --save</code></li></ol><p>Eso hoy por hoy installa bootstrap 3, pero puede instalar bootstrap 4 en el futuro. Ten en cuenta que ngx-bootstrap funciona con las dos versiones.</p><ol><li>abre <strong><strong>src/app/app.module.ts</strong></strong> y añade<br><code>import { AlertModule } from 'ngx-bootstrap'; ... @NgModule({ ... imports: [AlertModule.forRoot(), ... ], ... })</code></li><li>abre <strong><strong>angular-cli.json</strong></strong> e inserta una nueva entrada en el arreglo styles<br><code>"styles": [ "styles.css", "../node_modules/bootstrap/dist/css/bootstrap.min.css" ],</code></li><li>abre <strong><strong>src/app/app.component.html</strong></strong> y añade<br><code>&lt;alert type="success"&gt;hola&lt;/alert&gt;</code></li></ol><p><strong><strong>1.0.0-beta.10 o </strong>anteriores<strong>:</strong></strong></p><p>Si tu versión de angular-cli version es 1.0.0-beta.10 o anterior tienes que usar estos pasos.</p><p>Vete al directorio del proyecto y escribe</p><pre><code>npm install ngx-bootstrap --save</code></pre><p>abre <strong><strong>angular-cli-build.js</strong></strong> y añade esto</p><pre><code class="language-js">vendorNpmFiles: [
   ..................
   'ngx-bootstrap/**/*.js',
    ....................
  ]</code></pre><p>ahora abre <strong><strong>src/system-config.ts</strong></strong>, escribe</p><pre><code class="language-ts">const map:any = {
     ..................
   'ngx-bootstrap': 'vendor/ngx-bootstrap',
    ....................
}</code></pre><p>y</p><pre><code class="language-ts">const packages: any = {
  'ngx-bootstrap': {
    format: 'cjs',
    defaultExtension: 'js',
    main: 'ngx-bootstrap.js'
  }
};</code></pre><p><a href="https://stackoverflow.com/questions/37649164" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="accesskeyvalue">Acceso a key y value de un objecto que utiliza *ngFor</h3><!--kg-card-end: html--><blockquote>136+ votos<em><em>? 1</em></em>39,816+ vistas<br><em><em><a href="https://stackoverflow.com/users/5043867/pardeep-jain"><strong><strong>Pardeep Jain</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Tengo confusión sobre los objetos &nbsp;<code>Key y Value</code> en angular2 usando *ngFor para las iteraciones sobre el objeto. Sé que en angular 1.x hay una sintaxis como esta:</p><pre><code class="language-ts">ng-repeat="(key, value) in demo"</code></pre><p>pero en angular2 eso no me funciona. He probado lo siguiente pero tampoco funciona. &nbsp;Por favor decidme lo que estoy haciendo mal.</p><pre><code class="language-ts">&lt;ul&gt;
  &lt;li *ngFor='#key of demo'&gt;{{key}}&lt;/li&gt;
&lt;/ul&gt;

demo = {
    'key1': [{'key11':'value11'}, {'key12':'value12'}],
    'key2': [{'key21':'value21'}, {'key22':'value22'}],
  }</code></pre><p>Aquí está mi Plunker : <a href="http://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview" rel="noopener">http://plnkr.co/edit/mIj619FncOpfdwrR0KeG?p=preview</a></p><p>Quiero obtener &nbsp;<code>key1</code> y <code>key2</code> dinamicamente con *ngFor. He encontrado una idea usando pipe pero no sé como hacerlo. ¿Hay alguna pipe en Angular 2 que me permita hacerlo?</p><blockquote><a href="https://stackoverflow.com/users/1873365" rel="noopener"><strong><strong><em><em>Thierry Templier</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (134+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Puedes crear una pipe personalizada que devuelva la lista de keys para cada elemento. &nbsp;Algo como esto:</p><pre><code class="language-ts">import { PipeTransform, Pipe } from '@angular/core';

@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.push(key);
    }
    return keys;
  }
}</code></pre><p>y la usas así:</p><pre><code class="language-ts">&lt;tr *ngFor="let c of contenido"&gt;           
  &lt;td *ngFor="let key of c | keys"&gt;{{key}}: {{c[key]}}&lt;/td&gt;
&lt;/tr&gt;</code></pre><p><strong><strong>Edit</strong>ado</strong></p><p>También puedes devolver una entrada que contenga la key la la value:</p><pre><code class="language-ts">@Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
  transform(value, args:string[]) : any {
    let keys = [];
    for (let key in value) {
      keys.push({key: key, value: value[key]});
    }
    return keys;
  }
}</code></pre><p>y para usarla:</p><pre><code class="language-ts">&lt;span *ngFor="let c of contenido | keys"&gt;           
  Key: {{c.key}}, value: {{c.value}}
&lt;/span&gt;</code></pre><p><a href="https://stackoverflow.com/questions/35534959" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="cantbindtongfor">Excepción de Angular: Can’t bind to ‘ngFor’ since it isn’t a known native property (No se puede enlazar a 'ngFor' porque no es una propiedad nativa conocida).</h3><!--kg-card-end: html--><blockquote>134+ votos<em><em>? 6</em></em>3,054+ vistas<br><em><em><a href="https://stackoverflow.com/users/215945/mark-rajcok"><strong><strong>Mark Rajcok</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>¿Qué estoy haciendo mal?</p><pre><code class="language-ts">import {bootstrap, Component} from 'angular2/angular2'

@Component({
  selector: 'conf-charlas',
  template: `&lt;div *ngFor="charla of charlas"&gt;
     {{charla.titulo}} de {{charla.orador}}
     &lt;p&gt;{{charla.descripcion}}
   &lt;/div&gt;`
})
class ConfCharlas {
  talks = [ {titulo: 't1', orador: 'Brian', descripcion: 'talk 1'},
            {titulo: 't2', orador: 'Julie', descripcion: 'talk 2'}];
}
@Component({
  selector: 'mi-app',
  directives: [ConfCharlas],
  template: '&lt;conf-charlas&gt;&lt;/conf-charlas&gt;'
})
class App {}
bootstrap(App, [])</code></pre><p>El error:</p><pre><code class="language-bash">EXCEPTION: Template parse errors:
Can't bind to 'ngFor' since it isn't a known native property
("&lt;div [ERROR -&gt;]*ngFor="charla of charlas"&gt;</code></pre><blockquote><a href="https://stackoverflow.com/users/215945" rel="noopener"><strong><strong><em><em>Mark Rajcok</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (325+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Te falta <code>let</code> delante de &nbsp;<code>charla</code>:</p><pre><code class="language-ts">&lt;div *ngFor="let charla of charlas"&gt;</code></pre><p>Ten en cuenta que desde <a href="https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta17-2016-04-28" rel="noopener">beta.17</a> la sintaxis con &nbsp;<code>#...</code> para declarar variables locales en una directive estructural como NgFor se considera obsoleta. Usa <code>let</code> &nbsp;en su lugar.<br><code>&lt;div *ngFor="#charla of charlas"&gt;</code> ahora es <code> &lt;div *ngFor="let charla of charlas"&gt;</code></p><p>Respuesta original:</p><p>Te falta &nbsp;<code>#</code> delante de &nbsp;<code>charla</code>:</p><pre><code class="language-ts">&lt;div *ngFor="#charla of charlas"&gt;</code></pre><p>Es muy fácil olvidarse de <code>#</code>. Me gustaría que el mensaje de Angular fuera:<br><code>se te ha olvidado # otra vez</code>.</p><p><a href="https://stackoverflow.com/questions/34012291" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="fontawesome">¿Cómo se añade font-awesome a un proyecto Angular 2 + CLI </h3><!--kg-card-end: html--><blockquote>132+ votos<em><em>? 7</em></em>1,934+ vistas<br><em><em><a href="https://stackoverflow.com/users/1394625/nik"><strong><strong>Nik</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Estoy usando Angular 2+ y Angular CLI.</p><p>¿Cómo agrego font-awesome a mi proyecto?</p><blockquote><a href="https://stackoverflow.com/users/5904566" rel="noopener"><strong><strong><em><em>AIon</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (285+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Desde el lanzamiento final de &nbsp;Angular 2.0 , <strong>la <strong>estructur</strong>a<strong> </strong>de<strong> </strong>un proyecto de <strong>Angular2 CLI </strong>ha cambiado</strong> — no necesitas ningunos ficheros de vendedores -no system.js — solamente webpack. Esto es lo que tienes que hacer:</p><ol><li><code>npm install font-awesome --save</code></li><li>En el fichero angular-cli.json encuentra el arreglo <code>styles[]</code> y añade las referencias a font-awesome:<br><code>“apps”: [ { “root”: “src”, “outDir”: “dist”, …. “styles”: [ “styles.css”, “../node_modules/bootstrap/dist/css/bootstrap.css”, “../node_modules/font-awesome/css/font-awesome.css” // -webpack creara un enlacel automaticamente a css con esto!? ], … } ] ]</code></li><li>Pon algunos iconos de font-awesome en cualquier fichero html que quieras:<br><code>&lt;i class=”fa fa-american-sign-language-interpreting fa-5x” aria-hidden=”true”&gt; &lt;/i&gt;</code></li><li>Corre <code>ng build</code> y <code>ng serve</code> otra vez - porque los observadores son solamente para la carpeta src y no se observan los cambios en angular-cli.json.</li><li>¡Disfruta de tus impresionantes íconos!</li></ol><p><a href="https://stackoverflow.com/questions/38796541" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><!--kg-card-begin: html--><h3 id="httphttpc">Diferencia entre HTTP y HTTPClient en angular 4</h3><!--kg-card-end: html--><blockquote>130+ votos<em><em>? 4</em></em>7,082+ vistas<br><em><em><a href="https://stackoverflow.com/users/3551590/aiyoub-amini"><strong><strong>Aioub Amini</strong></strong></a><strong><strong> </strong></strong></em><strong>pregunta</strong><em><strong><strong>,</strong></strong></em></em></blockquote><p>Quiero saber cuál usar para crear un servicio web simulado para probar el programa Angular.</p><blockquote><a href="https://stackoverflow.com/users/2545680" rel="noopener"><strong><strong><em><em>AngularInDepth.com</em></em></strong></strong></a><strong><strong><em><em> </em></em></strong><em>contesta</em><strong><em><em>, (208+ </em></em></strong><em>votos</em><strong><em><em>)</em></em></strong></strong></blockquote><p>Usa la clase <code>HttpClient</code> de <code>HttpClientModule</code> si estás usando Angular 4.3.x a o posterior:</p><pre><code class="language-ts">import { HttpClientModule } from '@angular/common/http';

@NgModule({
 imports: [
   BrowserModule,
   HttpClientModule
 ],
 ...
 
 class MyService() {
    constructor(http: HttpClient) {...}</code></pre><p>Es una versión mejorada del módulo <code>http</code> de <code>@angular/http</code> con estas mejoras:</p><ul><li>Los interceptores permiten que la lógica del middleware se inserte en la canalización (pipeline)</li><li>Objetos de solicitud/respuesta inmutables</li><li>Eventos de progreso para la carga de solicitudes y la descarga de respuestas</li><li>Acceso tipado (typed) y síncrono al cuerpo (body) de la respuesta, incluyendo soporte para tipos de JSON</li><li>JSON se asume y ya no necesitas analizarlo explícitamente</li><li>Verificación Post-request &amp; testeado del framework basado en vaciado (flush)</li></ul><p>En el futuro, el antiguo http client quedará obsoleto. </p><p>También ten en cuenta que el antiguo http era inyectado con la clase &nbsp;<code>Http</code> en lugar del nuevo <code>HttpClient</code>:</p><pre><code class="language-ts">import { HttpModule } from '@angular/http';

@NgModule({
 imports: [
   BrowserModule,
   HttpModule
 ],
 ...
 
 class MiServicio() {
    constructor(http: Http) {...}</code></pre><p>Además, el nuevo <code>HttpClient</code> parece necesitar <code>tslib</code> en runtime, así que tienes que instalarlo con <code>npm i tslib</code> y actualizar &nbsp;<code>system.config.js</code> si estás usando<code>SystemJS</code>:</p><pre><code class="language-ts">map: {
     ...
    'tslib': 'npm:tslib/tslib.js',</code></pre><p>Y necesitas agregar otro mapeo (mapping) si usas SystemJS:</p><pre><code>'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js',</code></pre><p><a href="https://stackoverflow.com/questions/45129790" rel="noopener"><strong><strong>Source</strong></strong></a><br><strong><strong><a href="#tabladecontenidos">Top</a></strong></strong></p><p><strong>Eso es todo por hoy. Si te ha resultado útil este artículo, ayúdame a compartirlo. ? ? ?</strong></p><p><strong>Sígueme en <strong><a href="http://medium.com/wizardnet972" rel="noopener">Medium </a>o <a href="https://twitter.com/wizardnet972" rel="noopener">Twitter </a></strong>para leer más sobre Angular<strong>, webpack, typescript, nodejs </strong>y<strong> javascript! ? ? ?</strong></strong></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tutorial de Fetch API en JavaScript con ejemplos de JS Fetch, Post y Header ]]>
                </title>
                <description>
                    <![CDATA[ Artículo original escrito por: Manish Shivanandhan [https://www.freecodecamp.org/news/author/manishmshiva/] Artículo original: JavaScript Fetch API Tutorial with JS Fetch Post and Header Examples [https://www.freecodecamp.org/news/javascript-fetch-api-tutorial-with-js-fetch-post-and-header-examples/] Traducido y adaptado por: Gemma Fuster [/espanol/news/author/gemma/] Si estás escribiendo una aplicación web, es probable que tengas que trabajar con datos externos. Puede ser tu propia base de dat ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/tutorial-de-fetch-api-en-javascript-con-ejemplos-de-js-fetch-post-y-header/</link>
                <guid isPermaLink="false">625853ae9a87f708bdd1111f</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Mon, 18 Apr 2022 19:23:34 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/04/wall-2.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Artículo original escrito por</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> </strong></strong></strong></strong></strong></strong></strong></strong><a href="https://www.freecodecamp.org/news/author/manishmshiva/">Manish Shivanandhan</a><br><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Artículo original</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> </strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong><a href="https://www.freecodecamp.org/news/javascript-fetch-api-tutorial-with-js-fetch-post-and-header-examples/">JavaScript Fetch API Tutorial with JS Fetch Post and Header Examples</a><br><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Traducido y adaptado por</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> </strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong><a href="https://www.freecodecamp.org/espanol/news/author/gemma/">Gemma Fuster</a></p><p>Si estás escribiendo una aplicación web, es probable que tengas que trabajar con datos externos. Puede ser tu propia base de datos, una API de terceros, etc.</p><p>Cuando <a href="https://es.wikipedia.org/wiki/AJAX">AJAX </a>apareció por primera vez en 1999, nos mostró una forma mejor de construir aplicaciones web. AJAX fue un hito en el desarrollo web y es el concepto central detrás de muchas tecnologías modernas como React.</p><p>Antes de AJAX, tenías que volver a renderizar una página web completa, incluso para actualizaciones menores. Pero AJAX nos dio una forma de recuperar el contenido del backend y de actualizar los elementos de la interfaz de usuario seleccionados. Esto ayudó a los desarrolladores a mejorar la experiencia del usuario y a construir plataformas web más grandes y complicadas.</p><h2 id="curso-intensivo-sobre-rest-api">Curso intensivo sobre REST API</h2><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2022/04/image-5.png" class="kg-image" alt="image-5" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2022/04/image-5.png 600w, https://www.freecodecamp.org/espanol/news/content/images/2022/04/image-5.png 717w" width="600" height="400" loading="lazy"></figure><p>Ahora estamos en la era de las RESTful APIs. En pocas palabras, una REST API &nbsp;te permite enviar y extraer datos de un almacén de datos. Esta podría ser tu base de datos o el servidor de un tercero como &nbsp;Twitter API.</p><p>Hay varios tipos de REST APIs. Veamos los que usarás en la mayoría de los casos.</p><ul><li><strong><strong>GET</strong></strong> — Obtener datos de la API. Por ejemplo, obtener un usuario de Twitter en función de su nombre de usuario.</li><li><strong><strong>POST</strong></strong> — Empujar los datos a la API. Por ejemplo, crear un nuevo registro de usuario con nombre, edad y dirección de correo electrónico.</li><li><strong><strong>PUT</strong></strong> — Actualizar un registro existente con nuevos datos. Por ejemplo, actualizar la dirección de correo electrónico de un usuario.</li><li><strong><strong>DELETE</strong></strong> — Eliminar un registro. Por ejemplo, eliminar un usuario de la base de datos.</li></ul><p>Toda REST API tiene tres elementos. La solicitud (request), la respuesta (response) y los encabezados (header).</p><p><strong><strong>Request</strong></strong> — Estos son los datos que envías a la API, como una identificación de pedido (id) para obtener los detalles del pedido.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/08/2-6.png" class="kg-image" alt="2-6" width="600" height="400" loading="lazy"><figcaption>Sample Request</figcaption></figure><p><strong><strong>Response</strong></strong> — Los datos que obtengas del servidor después de una solicitud exitosa o fallida.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/08/3-5.png" class="kg-image" alt="3-5" width="600" height="400" loading="lazy"><figcaption>Sample Response</figcaption></figure><p><strong><strong>Headers</strong></strong> — Metadatos adicionales que se mandan a la API para ayudar al servidor a comprender qué tipo de solicitud se está mandando, por ejemplo, “content-type” (tipo de contenido).</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/08/4-2.png" class="kg-image" alt="4-2" width="600" height="400" loading="lazy"><figcaption>Sample Headers</figcaption></figure><p>La gran ventaja de usar una REST API es que puedes crear una sola capa de API para que la usen varias aplicaciones.</p><p>Si tienes una base de datos que deseas administrar mediante una aplicación web, móvil y de escritorio, todo lo que necesitas es una única capa de REST API.</p><p>Ahora que sabes cómo funcionan las REST APIs, veamos cómo podemos consumirlas.</p><h2 id="xmlhttprequest"><strong>XMLHttpRequest</strong></h2><p>Antes de que <a href="https://www.w3schools.com/js/js_json_intro.asp">JSON</a> se convirtiera en lo popular que es hoy, el formato principal del intercambio de datos fue XML. XMLHttpRequest() es una función de JavaScript que hace posible obtener datos de las API que devuelven datos en XML.</p><p>XMLHttpRequest nos da la opción de obtener datos XML desde el backend sin recargar toda la página.</p><p>Esta función ha crecido desde sus días iniciales cuando era solamente XML. Ahora es compatible con otros formatos de datos como JSON y texto sin formato.</p><p>Escribamos una simple llamada XMLHttpRequest a la API de GitHub para obtener mi perfil.</p><pre><code class="language-javascript">// funcion para cuando la llamada es exitosa
function exito() {
    var datos = JSON.parse(this.responseText); //convertir a JSON
    console.log(datos);
}

// funcion para la llamada fallida
function error(err) {
    console.log('Solicitud fallida', err); //los detalles en el objecto "err"
}

var xhr = new XMLHttpRequest(); //invocar nueva instancia de XMLHttpRequest
xhr.onload = exito; // llamar a la funcion exito si exitosa
xhr.onerror = error;  // llamar a la funcion error si fallida
xhr.open('GET', 'https://api.github.com/users/manishmshiva'); // Abrir solicitud GET
xhr.send(); // mandar la solicitud al vervidor.</code></pre><p>El código anterior enviará una solicitud GET a <a href="https://api.github.com/users/manishmshiva" rel="noopener">https://api.github.com/users/manishmshiva</a> para obtener mi información de GitHub en JSON. Si la respuesta es exitosa, imprimirá el siguiente JSON en la consola:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2020/08/5-2.png" class="kg-image" alt="5-2" width="600" height="400" loading="lazy"></figure><p>Si la solicitud falla, imprimirá este mensaje de error en la consola:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2020/08/8-1.png" class="kg-image" alt="8-1" width="600" height="400" loading="lazy"></figure><h2 id="fetch-api"><strong>Fetch API</strong></h2><p>La Fetch API es una versión más simple y fácil de usar para consumir recursos de forma asíncrona que una XMLHttpRequest . Fetch te permite trabajar con REST APIs con opciones adicionales, como almacenar datos en caché, leer respuestas de transmisión y más.</p><p>La diferencia principal &nbsp;es que Fetch funciona con promesas, no con devoluciones de llamada. Los desarrolladores de JavaScript se han alejado de las devoluciones de llamadas después de la introducción de las promesas.</p><p>Para una aplicación compleja, es posible que adquieras fácilmente el hábito de escribir devoluciones de llamadas (callbacks) que conduzcan a un infierno de llamadas.</p><p>Con las promesas, es fácil escribir y manejar solicitudes asincrónicas. Si no estás familiarizado con las promesas, <a href="https://es.javascript.info/promise-basics">puedes aprender como funcionan aqui</a>.</p><p>Así es como se quedaría la función que escribimos anteriormente usando fetch() en lugar de XMLHttpRequest:</p><pre><code class="language-javascript">// Solicitud GET (Request).
fetch('https://api.github.com/users/manishmshiva')
    // Exito
    .then(response =&gt; response.json())  // convertir a json
    .then(json =&gt; console.log(json))    //imprimir los datos en la consola
    .catch(err =&gt; console.log('Solicitud fallida', err)); // Capturar errores</code></pre><p>El primer parámetro de la función Fetch siempre debe ser la URL. Fetch entonces toma un segundo objeto JSON con opciones como method, headers, request body, etc.</p><p>Hay una diferencia importante entre el objeto de respuesta en XMLHttpRequest y Fetch.</p><p>XMLHttpRequest devuelve los datos como respuesta, mientras que el objeto de respuesta de Fetch contiene información sobre el objeto de respuesta en sí mismo. Esto incluye headers, status code, etc. Llamamos a la función “res.json()” para obtener los datos que necesitamos del objeto de respuesta.</p><p>Otra diferencia importante es que Fetch API no generará un error si la solicitud devuelve un código de estado 400 o 500. Todavía se marcará como una respuesta exitosa y se pasará a la función <code>.then</code>.</p><p>Fetch solo arroja un error si la solicitud en sí se interrumpe. Para manejar respuestas 400 y 500, puedes escribir una lógica personalizada usando 'response.status'. La propiedad 'status' te dará el código de estado de la respuesta devuelta.</p><p>Estupendo. Ahora que sabes cómo funciona la Fetch API, veamos un par de ejemplos más, sobre como pasar datos y trabajar con headers.</p><h2 id="trabajando-con-headers"><strong>Trabajando con Headers</strong></h2><p>Puedes pasar encabezados con la propiedad “headers”. &nbsp;Pasar un objeto JSON a la propiedad "headers" debería funcionar en la mayoría de los casos.</p><pre><code class="language-javascript">fetch('https://api.github.com/users/manishmshiva', {
  method: "GET",
  headers: {"Content-type": "application/json;charset=UTF-8"}
})
.then(response =&gt; response.json()) 
.then(json =&gt; console.log(json)); 
.catch(err =&gt; console.log(err));</code></pre><h2 id="pasando-datos-a-una-solicitud-post">Pasando datos a una solicitud POST</h2><p>Para una solicitud POST, puedes usar la propiedad “body” para pasar una cadena JSON como input. Date cuenta de que el "body" debe ser una cadena JSON, pero los encabezados (headers) deben ser un objecto JSON.</p><pre><code class="language-javascript">// datos mandados con la solicutud POST
let _datos = {
  titulo: "foo",
  principal: "bar", 
  Id:1
}

fetch('https://jsonplaceholder.typicode.com/posts', {
  method: "POST",
  body: JSON.stringify(_datos),
  headers: {"Content-type": "application/json; charset=UTF-8"}
})
.then(response =&gt; response.json()) 
.then(json =&gt; console.log(json));
.catch(err =&gt; console.log(err));</code></pre><p>La Fetch API todavía está en desarrollo. Podemos esperar mejoras en un futuro próximo.</p><p>Sin embargo, la mayoría de los navegadores admiten el uso de Fetch en sus aplicaciones. La tabla a continuación debería ayudarte a determinar qué navegadores lo admiten en la web y las aplicaciones móviles.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://www.freecodecamp.org/news/content/images/2020/08/6-2.png" class="kg-image" alt="6-2" width="600" height="400" loading="lazy"></figure><p>Espero que este artículo te haya ayudado a comprender cómo trabajar con la API Fetch. Asegúrate de probar Fetch en tu próxima aplicación web.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ ¿Qué es Hoisting en JavaScript? ]]>
                </title>
                <description>
                    <![CDATA[ Artículo original escrito por: Zach Snoek [https://www.freecodecamp.org/news/author/zachsnoek/] Artículo original: What is hoisting in JavaScript? [https://www.freecodecamp.org/news/what-is-hoisting-in-javascript/] Traducido y adaptado por: Gemma Fuster [/espanol/news/author/gemma/] En JavaScript, hoisting te permite usar funciones y variables antes de que se hayan declarado. En este post, aprenderemos qué es el hoisting y cómo funciona. ¿Qué es ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/que-es-hoisting-alzar-en-javascript/</link>
                <guid isPermaLink="false">61c7b8ea7ff87f092015bc4a</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Sat, 08 Jan 2022 12:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/12/js-hoisting.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Artículo original escrito por</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> </strong></strong></strong></strong><a href="https://www.freecodecamp.org/news/author/zachsnoek/">Zach Snoek</a><br><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Artículo original</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> </strong></strong></strong></strong></strong></strong></strong></strong><a href="https://www.freecodecamp.org/news/what-is-hoisting-in-javascript/">What is hoisting in JavaScript?</a><br><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>Traducido y adaptado por</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>:</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong> </strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong></strong><a href="https://www.freecodecamp.org/espanol/news/author/gemma/">Gemma Fuster</a></p><p>En JavaScript, hoisting te permite usar funciones y variables antes de que se hayan declarado. En este post, aprenderemos qué es el hoisting y cómo funciona.</p><h2 id="-qu-es-hoisting">¿Qué es hoisting?</h2><p>Echa un vistazo a este código y adivina qué sucede cuando se ejecuta:</p><pre><code class="language-js">console.log(foo);
var foo = 'foo';
</code></pre><p>Puede que te sorprenda saber que este código genera <code>undefined</code> y que no falla o genera un error – a pesar de que <code>foo</code> se asigna después de la línea <code>console.log</code></p><p>Esto se debe a que el intérprete de JavaScript divide la declaración y asignación de funciones y variables: JavaScript "hoists" o "alza" tus declaraciones a la parte superior de su scope (ámbito) antes de la ejecución.</p><p>A esto se le llama hoisting, y nos permite usar <code>foo</code> antes de su declaración en el ejemplo anterior.</p><p>Echemos un vistazo más profundo a las funciones y al hoisting de variables para comprender qué significa esto y cómo funciona.</p><h2 id="hoisting-de-variables-en-javascript"><strong>Hoisting de variables en JavaScript</strong></h2><p>Como recordatorio, en JavaScript, <strong>declaramos </strong>una variable con &nbsp;<code>var</code>, <code>let</code>, y<code>const</code>. Por ejemplo:</p><pre><code class="language-js">var foo;
let bar;
</code></pre><p><strong>Asignamos </strong>un valor a una variable usando el operador de asignación:</p><pre><code class="language-jsx">// Declaracion
var foo;
let bar;

// Asignacion
foo = 'foo';
bar = 'bar';
</code></pre><p>En muchos casos, podemos combinar la declaración y la asignación en un solo paso:</p><pre><code class="language-js">var foo = 'foo';
let bar = 'bar';
const baz = 'baz';
</code></pre><p>El hoisting de variables actúa de manera diferente dependiendo de cómo se declare la variable. Comencemos por comprender el comportamiento de las variables declaradas con <code>var</code>.</p><h3 id="hoisting-de-variables-con-var"><strong>Hoisting de variables con <code>var</code></strong></h3><p>Cuando el intérprete hace hoisting de una variable declarada con <code>var</code>, inicializa su valor a <code>undefined</code>. La primera línea de código a continuación muestra <code>undefined</code>:</p><pre><code class="language-js">console.log(foo); // undefined

var foo = 'bar';

console.log(foo); // "bar"
</code></pre><p>Como hemos dicho antes, hoisting proviene de que el intérprete de JavaScript divida la declaración y la asignación de variables. Podemos lograr lo mismo manualmente si dividimos la declaración y la asignación en dos pasos:</p><pre><code class="language-js">var foo;

console.log(foo); // undefined

foo = 'foo';

console.log(foo); // "foo"
</code></pre><p>Recuerda que la primera <code>console.log(foo)</code> muestra<code>undefined</code> porque a la variable <code>foo</code> se le hace hoisting y se le asigna un valor por defecto (no porque la variable nunca sea declarada). El uso de una variable no declarada nunca mostrará un <code>ReferenceError</code> en lugar de un <code>undefined</code>:</p><pre><code class="language-js">console.log(foo); // Uncaught ReferenceError: foo is not defined
</code></pre><p>El uso de una variable no declarada antes de su asignación también mostrará un <code>ReferenceError</code> porque no se ha hecho hoisting a ninguna declaración:</p><pre><code class="language-js">console.log(foo); // Uncaught ReferenceError: foo is not defined
foo = 'foo';      // asignar una variable que no esta declarada es válido
</code></pre><p>A estas alturas, debes estar pensando, "Es un poco raro que JavaScript nos permita acceder a las variables antes de que se declaren." Este comportamiento es una parte inusual de JavaScript y puede conducir a errores. Por lo general, no es recomendable usar una variable antes de que sea declarada.</p><p>Afortunadamente, declarar variables con <code>let</code> y <code>const</code>, introducidas en ECMAScript 2015, cambia este comportamiento.</p><h3 id="hoisting-de-variables-con-let-y-const"><strong>Hoisting de variables con <code>let</code> y <code>const</code></strong></h3><p>Las variables declaradas con <code>let</code> y <code>const</code> también reciben hoisting, pero no son inicializadas con un valor por defecto. Acceder a una variable declarada con <code>let</code> o <code>const</code> antes de que sea declarada resulta en un <code>ReferenceError</code>:</p><pre><code class="language-js">console.log(foo); // Uncaught ReferenceError: Cannot access 'foo' before initialization

let foo = 'bar';  // lo mismo para variables declaradas con const
</code></pre><p>Observa que el intérprete sigue haciendo hoisting a <code>foo</code>: el mensaje de error nos dice que la variable se inicializa en algún lugar.</p><h3 id="la-zona-muerta-temporal">La zona muerta temporal</h3><p>La razón por la que obtenemos un error de referencia cuando intentamos acceder a una variable declarada con <code>let</code> o <code>const</code> antes de su declaración se debe a la zona muerta temporal (temporal dead zone, TDZ).</p><p>La TDZ comienza al principio del ámbito de la variable y finaliza cuando se declara. El acceso a la variable en esta zona TDZ lanza un <code>ReferenceError</code>.</p><p>Aquí va un ejemplo con un bloque explícito que muestra el inicio y el final de la TDZ de foo:</p><pre><code class="language-js">{
 	// Comienzo de TDZ de foo
  	let bar = 'bar';
	console.log(bar); // "bar"

	console.log(foo); // ReferenceError porque estamos en la TDZ de foo

	let foo = 'foo';  // Final de TDZ de foo
}
</code></pre><p>La TDZ también está presente en los parámetros de función predeterminados (por defecto), que se evalúan de izquierda a derecha. En el siguiente ejemplo, <code>bar</code> está en la zona TDZ hasta que se establece su valor predeterminado:</p><pre><code class="language-js">function foobar(foo = bar, bar = 'bar') {
  console.log(foo);
}
foobar(); // Uncaught ReferenceError: Cannot access 'bar' before initialization
</code></pre><p>Pero este código funciona porque podemos acceder a <code>foo</code> desde fuera de su TDZ:</p><pre><code class="language-jsx">function foobar(foo = 'foo', bar = foo) {
  console.log(bar);
}
foobar(); // "foo"
</code></pre><h3 id="typeof-en-la-tdz"><strong><code>typeof</code> en la TDZ</strong></h3><p>El uso de una variable <code>let</code> o <code>const</code> como operando del operador &nbsp;<code>typeof</code> en la TDZ arrojará un error: </p><pre><code class="language-js">console.log(typeof foo); // Uncaught ReferenceError: Cannot access 'foo' before initialization
let foo = 'foo';
</code></pre><p>Este comportamiento es consistente con los otros casos de <code>let</code> y <code>const</code> que hemos visto en la TDZ. Encontramos un <code>ReferenceError</code> porque <code>foo</code> es declarada, pero no inicializada – debemos tener en cuenta que la estamos usando antes de la inicialización.</p><p>Sin embargo, no pasa cuando se utiliza una variable con <code>var</code> antes de que sea declarada porque se inicializa con <code>undefined</code> cuando se le hace el hoisting:</p><pre><code class="language-jsx">console.log(typeof foo); // "undefined"
var foo = 'foo';
</code></pre><p>Además, esto es sorprendente porque podemos comprobar el tipo de una variable que no existe sin que nos dé un error. <code>typeof</code> devuelve una cadena de forma segura:</p><pre><code class="language-js">console.log(typeof foo); // "undefined"
</code></pre><p>De hecho, con la introducción de <code>let</code> y <code>const</code> se rompe la garantía de <code>typeof</code> de siempre devolver un valor cadena para cualquier operando.</p><h2 id="hoisting-de-funciones-en-javascript"><strong>Hoisting de funciones en JavaScript</strong></h2><p>Las declaraciones de funciones también son sometidas a hoisting. Esto nos permite llamar a funciones antes de que sean definidas. Por ejemplo, el código siguiente termina con éxito y devuelve &nbsp;<code>"foo"</code>:</p><pre><code class="language-js">foo(); // "foo"

function foo() {
	console.log('foo');
}
</code></pre><p>Ten en cuenta que solamente se hace hoisting a las declaraciones de función, no a las expresiones de función. Esto debería tener sentido: como acabamos de ver, a las asignaciones de variables no se les hace hoisting.</p><p>Si intentamos llamar a la variable a la que se asignó la expresión de la función, obtendremos un &nbsp;<code>TypeError</code> o <code>ReferenceError</code>, dependiendo del ámbito de la variable:</p><pre><code class="language-js">foo(); // Uncaught TypeError: foo is not a function
var foo = function () { }

bar(); // Uncaught ReferenceError: Cannot access 'bar' before initialization
let bar = function () { }

baz(); // Uncaught ReferenceError: Cannot access 'baz' before initialization
const baz = function () { }
</code></pre><p>Esto difiere de llamar a una función que nunca ha sido declarada, que arroja una <code>ReferenceError</code>:</p><pre><code class="language-js">foo(); // Uncaught ReferenceError: baz is not defined
</code></pre><h2 id="c-mo-utilizar-hoisting-en-javascript">Cómo utilizar<strong> hoisting en JavaScript</strong></h2><h3 id="hoisting-de-variables"><strong>Hoisting de variables</strong></h3><p>Debido a la confusión que el hoisting con variables <code>var</code> puede crear, es mejor evitar usar las variables antes de que sean declaradas. &nbsp;Si estás escribiendo código en un <a href="https://es.wikipedia.org/wiki/Proyecto_Greenfield">proyecto greenfield</a>, deberías usar <code>let</code> y <code>const</code> para que esto se cumpla.</p><p>Si estás trabajando en una base de código anterior o tienes que usar <code>var</code> por otros motivos, <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/var#elevaci%C3%B3n_de_variables">MDN recomienda</a> que escribas las declaraciones <code>var</code> lo más cerca posible de la parte superior de su scope. Con esto se consigue que el scope de las variables sea más claro.</p><p>También puedes considerar usar la regla de ESLint <code>no-use-before-define</code>, que asegura que no se use una variable antes de su declaración.</p><h3 id="hoisting-de-funciones"><strong>Hoisting de funciones</strong></h3><p>El Hoisting de funciones es útil porque podemos dejar la implementación de la función más abajo en el archivo y dejar que el lector se concentre en lo que está haciendo el código. En otras palabras, podemos abrir un archivo y ver qué hace el código sin entender primero cómo está implementado.</p><p>Toma el siguiente ejemplo:</p><pre><code class="language-js">reiniciarPuntos();
dibujarTablero();
poblarTablero();
comenzarJuego();

function reiniciarPuntos() {
	console.log("Reinicializando puntos");
}

function dibujarTablero() {
	console.log("Dibujando tablero");
}

function poblarTablero() {
	console.log("Poblando tablero");
}

function comenzarJuego() {
	console.log("Comenzando juego");
}
</code></pre><p>Inmediatamente, tenemos una idea de lo que hace este código sin tener que leer todas las declaraciones de funciones.</p><p>Sin embargo, el uso de funciones antes de su declaración es una cuestión de preferencia personal. Algunos desarrolladores, como Wes Bos, prefieren evitar esto y colocar funciones en módulos que se pueden importar según sea necesario. </p><p>La guía de estilo de Airbnb lleva esto más allá y fomenta las expresiones de función nombradas sobre las declaraciones para evitar la referencia antes de la declaración:</p><blockquote>Las declaraciones de funciones estan sometidas a hoisting, lo que significa que es fácil, demasiado fácil, hacer referencia a la función antes de que se defina en el archivo. Esto perjudica la legibilidad y la facilidad de mantenimiento.<br><br>Si encuentras que la definición de una función es lo suficientemente grande o compleja como para interferir con la comprensión del resto del archivo, entonces quizás sea el momento de extraerla a su propio módulo.</blockquote><h2 id="conclusi-n"><strong>Conclusi</strong>ó<strong>n</strong></h2><p>Gracias por leer, espero que esta publicación te haya ayudado a aprender sobre hoisting en JavaScript. ¡Puedes contactar conmigo en <a href="https://www.linkedin.com/in/zach-snoek-5b327b179/">LinkedIn</a> si quieres o si tienes alguna pregunta!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo trabajar de manera óptima con bases de datos relacionales ]]>
                </title>
                <description>
                    <![CDATA[ Artículo original escrito por Milap Neupane [https://www.freecodecamp.org/news/author/milapneupane/] Artículo originalHow to work optimally with relational databases [https://www.freecodecamp.org/news/how-to-work-optimally-with-relational-databases-627073f82d56/] Traducido y adaptado por Gemma Fuster [/espanol/news/author/gemma/] Las bases de datos relacionales manejan los datos sin problemas, ya sea trabajando con volúmenes pequeños o procesando millones de filas. Veremos cómo podemos utilizar ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-trabajar-de-manera-optima-con-bases-de-datos-relacionales/</link>
                <guid isPermaLink="false">617004dd56587409993535cc</guid>
                
                    <category>
                        <![CDATA[ Programación ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Fri, 29 Oct 2021 12:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/10/mysql.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><strong><strong>Artículo original escrito por </strong></strong><a href="https://www.freecodecamp.org/news/author/milapneupane/">Milap Neupane</a><br><strong><strong>Artículo original &nbsp;</strong></strong><a href="https://www.freecodecamp.org/news/how-to-work-optimally-with-relational-databases-627073f82d56/">How to work optimally with relational databases</a><br><strong><strong>Traducido y adaptado por</strong> </strong><a href="https://www.freecodecamp.org/espanol/news/author/gemma/">Gemma Fuster</a></p><p>Las bases de datos relacionales manejan los datos sin problemas, ya sea trabajando con volúmenes pequeños o procesando millones de filas. Veremos cómo podemos utilizar las bases de datos relacionales de acuerdo con nuestras necesidades y sacarles el máximo partido.</p><p>MySQL ha sido una opción popular para empresas grandes y pequeñas debido a su capacidad de escalabilidad. De manera similar, PostgreSQL también ha experimentado un aumento en popularidad.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/NuCURJVqv3ixjGlK-U2yBGDWGzmoloI9PzIe" class="kg-image" alt="NuCURJVqv3ixjGlK-U2yBGDWGzmoloI9PzIe" width="800" height="418" loading="lazy"><figcaption>Photo source: <a href="https://insights.stackoverflow.com/survey/2018/" rel="noopener" target="_blank" title="" style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 17.6px; margin: 0px; padding: 0px; vertical-align: baseline; background-color: transparent; color: var(--gray90); cursor: pointer; text-decoration: underline; word-break: break-word;">https://insights.stackoverflow.com/survey/2018/</a></figcaption></figure><blockquote>Según <a href="https://insights.stackoverflow.com/survey/2018/">la encuesta de Stack Overflow 2018</a>, MySQL es la base de datos más popular entre todos los usuarios.</blockquote><p>Los ejemplos descritos anteriormente utilizan InnoDB como motor de almacenamiento para MySQL. No son solamente relevantes en MySQL sino también en otras bases de datos relacionales como PostgreSQL. &nbsp;Todas las comparativas se realizan en una computadora con 8GB de RAM y con un procesador i5 a 2.7 GHz.</p><p>Comencemos con los conceptos básicos de cómo la base de datos relacional almacena los datos.</p><h3 id="entendiendo-las-bases-de-datos-relacionales"><strong>Entendiendo las bases de datos relacionales</strong></h3><h4 id="almacenamiento"><strong>Almacenamiento</strong></h4><p>MySQL es una base de datos relacional donde los <strong>datos (data</strong>) estan representados en <strong>tuplas o lista de registros (tuples)</strong>, agrupadas en <strong>relaciones (<strong>relations</strong>)</strong>. Un tupla se representa por sus atributos (attributes).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/5aDL3AR1tfjEnDtw4rPGQYskfOyDJ-V2RBgg" class="kg-image" alt="5aDL3AR1tfjEnDtw4rPGQYskfOyDJ-V2RBgg" width="800" height="374" loading="lazy"><figcaption>Image source: <a href="https://commons.wikimedia.org/wiki/File:Relational_database_terms.svg" rel="noopener" target="_blank" title="" style="box-sizing: inherit; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 17.6px; margin: 0px; padding: 0px; vertical-align: baseline; background-color: transparent; color: var(--gray90); cursor: pointer; text-decoration: underline; word-break: break-word;">https://commons.wikimedia.org/wiki/File:Relational_database_terms.svg</a></figcaption></figure><p>Supongamos que tenemos una aplicación en la que las personas pueden prestar libros. Necesitaremos almacenar todas las transacciones de préstamo de libros. Para almacenarlos, hemos diseñado una tabla relacional simple con el siguiente comando:</p><pre><code>&gt; CREATE TABLE libro_transacciones ( id INTEGER NOT NULL   AUTO_INCREMENT, libro_id INTEGER, prestatario_id INTEGER, prestador_id INTEGER, retorno_fecha DATE, PRIMARY KEY (id));</code></pre><p>La tabla es:</p><pre><code>libro_transacciones
------------------------------------------------
id  prestatario_id  prestador_id  libro_id  retorno_fecha</code></pre><p>El <strong><strong>id</strong></strong> es la clave principal y <strong>prestatario<strong>_id</strong></strong>, <strong>prestador<strong>_id</strong></strong>, <strong>libro<strong>_id</strong></strong> son las claves foráneas. Después de lanzar nuestra aplicación, hay registradas pocas transacciones:</p><pre><code>libro_transacciones
----------------------------------------------------------
id  prestatario_id  prestador_id  libro_id  retorno_fecha
----------------------------------------------------------
1                1             1          1    2018-01-13
2                2             3          2    2018-01-13
3                1             2          1    2018-01-13</code></pre><h4 id="obteniendo-los-datos">Obteniendo los datos</h4><p>Tenemos una página de tablero para cada usuario donde pueden ver las transacciones de sus libros prestados. Busquemos las transacciones de libros para un usuario:</p><pre><code>&gt; SELECT * FROM libro_transacciones WHERE prestatario_id = 1;
libro_transacciones
---------------------------------------------------------
id  prestatario_id  prestador_id  libro_id  retorno_fecha
---------------------------------------------------------
1                1             1          1    2018-01-13
2                1             2          1    2018-01-13</code></pre><p>Esto escanea la relación secuencialmente y nos da los datos para el usuario. Esto es muy rápido, ya que hay muy pocos datos en la relación. Para ver la hora exacta de ejecución de la consulta, <strong>configura <strong>profiling</strong></strong> a true (verdadero) ejecutando lo siguiente:</p><pre><code>&gt; set profiling=1;</code></pre><p>Una vez que profiling está configurado, ejecuta la misma consulta nuevamente y luego ejecuta esto para ver el <strong>tiempo de ejecución<strong>:</strong></strong></p><pre><code>&gt; show profiles;</code></pre><p>Esto devolverá la duración de la consulta que hemos ejecutado.</p><pre><code>Query_ID | Duration   | Query
       1 | 0.00254000 | SELECT * FROM libro_transacciones ...</code></pre><p>La ejecución parece muy buena (rápida).</p><p>Poco a poco, la tabla libro_transacciones se empieza a llenar de datos, a medida que aumentan las transacciones.</p><h3 id="el-problema"><strong>El problema</strong></h3><p>Esto incrementa el número de <strong><strong>tupl</strong>a<strong>s</strong></strong> de la relación. Con esto, el tiempo que lleva recuperar las transacciones del libro para el usuario comenzará a tomar más y más tiempo. &nbsp;MySQL necesita pasar por todas las tuplas para encontrar el resultado.</p><p>Para insertar muchos datos en la tabla, he escrito el siguiente procedimiento almacenado:</p><pre><code>DELIMITER //
 CREATE PROCEDURE insertarMuchos()
   BEGIN
   DECLARE i INT DEFAULT 1;
   WHILE (i &lt;= 100000) DO
    INSERT INTO libro_transacciones (prestatario_id, prestador_id, libro_id,   retorno_fecha) VALUES ((FLOOR(1 + RAND() * 60)), (FLOOR(1 + RAND() * 60)), (FLOOR(1 + RAND() * 60)), CURDATE());
    SET i = i+1;
   END WHILE;
 END //
 DELIMITER ;
* Ha tardado 7 minutos en insertar 1.5 millines de datos</code></pre><p>Esto inserta 100,000 registros aleatorios en la tabla libro_transacciones. Al ejecutar esto, el profiler muestra un ligero aumento en el tiempo de ejecución:</p><pre><code>Query_ID | Duration   | Query
       1 | 0.07151000 | SELECT * FROM libro_transacciones ...</code></pre><p>Agreguemos algunos datos más ejecutando el procedimiento anterior y veamos qué sucede. Con más y más datos agregados, la duración de la consulta aumenta. Con 1,5 millones de datos insertados en la tabla, ahora el tiempo de respuesta aumenta.</p><pre><code>Query_ID | Duration   | Query
       1 | 0.36795200 | SELECT * FROM libro_transacciones ...</code></pre><p>Esta es solamente una consulta simple con un valor integer (entero).</p><p>Con más consultas compuestas, consultas ordenadas y consultas con recuento, el tiempo de ejecución empeora aún más.</p><p>Esto no parece ser mucho tiempo para una consulta, pero cuando tenemos miles o incluso millones de consultas ejecutándose cada minuto, esto hace una gran diferencia.</p><p>Habrá mucho más tiempo de espera y esto obstaculizará el rendimiento general de la aplicación. El tiempo de ejecución para la misma consulta aumentó de 2 ms a 370 ms.</p><h3 id="recuperando-la-velocidad">Recuperando la velocidad</h3><h4 id="index"><strong>Index</strong></h4><p>MySQL, y otras bases de datos proporcionan indexación, una estructura de datos que ayuda a recuperar datos más rápido.</p><p>Hay diferentes tipos de indexación en MySQL:</p><ul><li><strong>Clave primaria<strong> </strong></strong>— Index agregado a la clave primaria. Por defecto, las claves primarias siempre están indexadas. Esto también asegura que las dos filas no tengan el mismo valor de clave principal.</li><li><strong><strong>Unique — </strong></strong>El index (índice) de Unique key index asegura que no haya dos filas en una relación que tengan el mismo valor. Se pueden almacenar varios valores nulos con un index de Unique Key .</li><li><strong><strong>Index — </strong></strong>Adición a cualquier otro campo que no sea la clave principal.</li><li><strong><strong>Full Text — </strong></strong>el index de Full text ayuda a las consultas de datos basados en caracteres.</li></ul><p>Hay dos formas principales de almacenar un índice:</p><p><strong><strong>Hash</strong></strong> — esto se usa principalmente para una coincidencia exacta (=), y no funciona con comparaciones (≥, ≤)</p><p><strong><strong>B-Tree</strong></strong> — Esta es la forma más común en la que se almacenan los tipos de índices (indexes) mencionados anteriormente.</p><p>MySQL utiliza un B-Tree como formato de indexación por defecto. Los datos se almacenan en un<a href="https://es.wikipedia.org/wiki/%C3%81rbol_binario"> árbol binario(binary tree)</a> lo que hace que la recuperación de datos sea rápida.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/xUuJBk8kDuyCrIzQTpfznpiwENHzXr5gMLYC" class="kg-image" alt="xUuJBk8kDuyCrIzQTpfznpiwENHzXr5gMLYC" width="800" height="439" loading="lazy"><figcaption>B-Tree data storage format</figcaption></figure><p>La organización de datos realizada por el B-tree ayuda a omitir el escaneo completo de la tabla en todas las tuplas de nuestra relación.</p><p>Hay un total de 16 nodos en el árbol (B-Tree) anterior. Si necesitamos encontrar el número 6, solamente necesitamos hacer un número total de 3 escaneos para obtenerlo. Esto ayuda a mejorar el rendimiento de la búsqueda.</p><p>Para mejorar el rendimiento en libro_transacciones, agreguemos el index en el campo prestador_id.</p><pre><code>&gt; CREATE INDEX prestadorId ON libro_transaccciones(prestador_id)
----------------------------------------------------
* Ha tardado unos 6.18sec</code></pre><p>El comando anterior agrega un index al campo prestador_id. Veamos cómo esto afecta el rendimiento de los 1,5 millones de datos que tenemos al ejecutar la misma consulta nuevamente.</p><pre><code>&gt; SELECT * FROM libro_transacciones WHERE prestador_id = 1;
Query_ID | Duration   | Query
       1 | 0.00787600 | SELECT * FROM libro_transacciones ...</code></pre><p>Woohoo! Ya hemos vuelto.</p><p>Es tan rápido como cuando solo había 3 registros en nuestra relación. Con el índice (index) correcto agregado, podemos ver una mejora dramática en la duración.</p><h4 id="-ndice-compuesto-y-nico">Índice compuesto y único</h4><p>El índice que hemos agregado es un índice de campo único. Los índices también se pueden agregar a un campo compuesto.</p><p>Si nuestra consulta involucrara varios campos, un índice compuesto nos ayudaría. Podemos agregar un índice compuesto de la siguiente forma:</p><pre><code>&gt; CREATE INDEX prestadorRetornoFecha ON libro_transacciones(pretador_id, retorno_fecha);</code></pre><h4 id="otro-uso-para-los-ndices">Otro uso para los índices</h4><p>Las consultas no son para lo único que sirven los índices. Además se puedan usar para la cláusula <strong><strong>ORDER BY</strong></strong>. Ordenemos los registros en base a prestador_id.</p><pre><code>&gt; SELECT * FROM libro_transacciones ORDER BY prestador_id;
1517185 rows in set (4.08 sec)</code></pre><p><strong><strong>4.08</strong></strong> <strong><strong>sec</strong></strong>, ¡es mucho! ¿qué ha pasado? Tenemos el índice. Profundicemos en cómo se ejecuta la consulta con la ayuda de la cláusula <strong>EXPLAIN</strong>.</p><h4 id="usando-explain"><strong>Usando Explain</strong></h4><p>Podemos agregar una cláusula explain para ver cómo se ejecutará la consulta en nuestro conjunto de datos actual.</p><pre><code>&gt; EXPLAIN SELECT * FROM libro_transacciones ORDER BY prestador_id;
</code></pre><p>El resultado es:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/ZDNJi8luN9QYAnV54eRQ4WZp6WMCQQLnGdOY" class="kg-image" alt="ZDNJi8luN9QYAnV54eRQ4WZp6WMCQQLnGdOY" width="800" height="123" loading="lazy"><figcaption>Using explain to see how the query will be executed</figcaption></figure><p>Hay varios campos que explican las devoluciones. Veamos la tabla anterior e identifiquemos el problema.</p><p><strong><strong>rows</strong> (filas)<strong>: </strong></strong>Número total de filas que se analizarán</p><p><strong><strong>filtered</strong> (filtrado)<strong>: </strong></strong>El porcentaje de fila que se escaneará para obtener los datos.</p><p><strong><strong>type</strong> (tipo)<strong>:</strong> </strong>Se da si se está utilizando el índice. ALL significa que no está usando index.</p><p><strong><strong>possible_keys, key, key_len</strong></strong> son NULL, lo que significa que no se está utilizando ningún índice.</p><p>Entonces, ¿por qué la consulta no usa el índice?</p><p>Es porque tenemos <code>select *</code> en la consulta, lo que significa que estamos seleccionando todos los campos de nuestra relación.</p><p>El índice solo tiene información sobre los campos que están indexados y no sobre otros campos. Esto significa que MySQL deberá ir a la tabla principal para recuperar datos nuevamente.</p><p>Entonces, ¿cómo deberíamos escribir la consulta?</p><h4 id="selecciona-solo-el-campo-requerido">Selecciona solo el campo requerido</h4><p>Para eliminar la necesidad de ir a la tabla principal para la consulta, necesitamos seleccionar solo el valor que está presente en la tabla de índice. Así que cambiemos la consulta a:</p><pre><code>&gt; SELECT prestador_id FROM libro_transacciones ORDER BY prestador_id;
</code></pre><p>Esto devolverá el resultado en 0,46 segundos, que es mucho más rápido. Pero todavía hay margen de mejora.</p><p>Como esta consulta se realiza en todos los 1,5 millones de registros que tenemos, está tomando un poco más de tiempo, ya que necesita cargar datos en la memoria.</p><h4 id="usa-limit"><strong>Usa Limit</strong></h4><p>Es posible que no necesitemos todos los 1,5 millones de datos al mismo tiempo. Entonces, en lugar de obtener todos los datos, usar LIMIT y obtener datos en lotes es una manera &nbsp;mejor de hacerlo.</p><pre><code>&gt; SELECT prestador_id
  FROM libro_transacciones
  ORDER BY prestador_id LIMIT 1000;</code></pre><p>Con un límite establecido, el tiempo de respuesta mejora drásticamente y se ejecuta en 0,0025 segundos. Ahora podemos buscar el siguiente lote con <strong>OFFSET</strong>.</p><pre><code>&gt; SELECT prestador_id
  FROM libro_transacciones
  ORDER BY prestador_id LIMIT 1000 OFFSET 1000;</code></pre><p>Esto buscará el siguiente lote de 1000 filas. Con esto podemos aumentar el desplazamiento y el límite para obtener todos los datos. ¡Pero hay un "te pillé"! Con un aumento en la compensación, el rendimiento de la consulta disminuye.</p><p>Esto se debe a que MySQL escaneará todos los datos para alcanzar el punto de compensación. Por lo tanto, es mejor no utilizar un desplazamiento más alto.</p><h4 id="-qu-pasa-con-la-consulta-count-recuento-">¿Qué pasa con la consulta Count (recuento)?</h4><p>El motor InnoDB tiene la capacidad de escribir simultáneamente. Esto lo hace altamente escalable y mejora el rendimiento por segundo.</p><p>Pero esto tiene un precio. InnoDB no puede agregar un contador de caché para el número de registros en ninguna tabla. Por lo tanto, el recuento debe realizarse en tiempo real escaneando todos los datos filtrados. Esto hace que la consulta COUNT sea lenta.</p><p>Por lo tanto, se recomienda calcular los datos de recuento resumidos en la lógica de la aplicación cuando se trata de una gran cantidad de datos.</p><h3 id="-por-qu-no-agregar-un-ndice-a-todos-los-campos">¿Por qué no agregar un índice a todos los campos?</h3><p>Agregar índice ayuda a mejorar mucho el rendimiento, pero también tiene un precio. Debe utilizarse de forma eficaz. Agregar un índice a más campos tiene los siguientes problemas:</p><ul><li>Necesita mucha memoria, una computadora más grande</li><li>Cuando eliminamos, hay una reindexación (eliminaciones intensivas de CPU y más lentas)</li><li>Cuando agregamos algo, hay reindexación (inserciones intensivas de CPU y más lentas)</li><li>Los cambios a un registro no reindexan por completo, por lo que la actualización es más rápida y eficiente en la CPU.</li></ul><p>Ahora tenemos claro que agregar un índice ayuda mucho. Pero no podemos seleccionar todos los datos, excepto los que están indexados para un rendimiento rápido.</p><p>¿cómo podemos seleccionar todos los atributos y seguir obteniendo un rendimiento rápido?</p><h3 id="particionamiento-partitioning-"><strong>Particionamiento (partitioning)</strong></h3><p>Cuando creamos índices, solamente tenemos información sobre el campo que está indexado. Pero no tenemos datos de los campos que no están presentes en el índice.</p><p>Entonces, como dijimos anteriormente, MySQL necesita mirar hacia atrás en la tabla principal para obtener los datos de otros campos. Esto puede ralentizar el tiempo de ejecución.</p><p>La forma en que podemos resolver esto es mediante particiones.</p><p>El particionamiento es una técnica en la que MySQL divide los datos de una tabla en varias tablas, pero los administra como una sola tabla.</p><p>Al realizar cualquier tipo de operación en la tabla, necesitamos especificar qué partición se está utilizando. Con los datos desglosados, MySQL tiene un conjunto de datos más pequeño para consultar. Determinar la partición correcta de acuerdo con las necesidades es clave para un alto rendimiento.</p><p>Pero si seguimos usando la misma máquina, ¿escalará?</p><h3 id="fragmentaci-n-sharding-">Fragmentación (<strong>Sharding)</strong></h3><p>Con un gran conjunto de datos, almacenar todos sus datos en la misma máquina puede resultar problemático.</p><p>Una partición específica puede ser muy grande y necesitar más consultas, mientras que otras menos. Entonces uno afectará a otro. No pueden escalarse por separado.</p><p>Supongamos que los datos de los últimos tres meses son los más utilizados, mientras que los más antiguos se utilizan menos. Quizás los datos recientes en su mayoría se actualizan / crean, mientras que los datos antiguos en su mayoría solo se leen.</p><p>Para resolver este problema, podemos mover la partición de los últimos tres meses a otra máquina. La fragmentación es una forma en la que dividimos un gran conjunto de datos en fragmentos más pequeños y lo pasamos a RDBMS separados. En otras palabras, la fragmentación también se puede llamar "partición horizontal".</p><p>Las bases de datos relacionales tienen la capacidad de escalar a medida que crece la aplicación. Es necesario encontrar el índice correcto y ajustar la infraestructura según las necesidades.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo agregar un formulario Netlify a una aplicación React construida con create-react-app ]]>
                </title>
                <description>
                    <![CDATA[ Artículo original escrito por Joseph Mawa [https://www.freecodecamp.org/news/author/joseph/] Artículo original How to Add a Netlify Form to a React App Built with create-react-app [https://www.freecodecamp.org/news/how-to-add-a-netlify-form-to-a-react-app/] Traducido y adaptado por Gemma Fuster [/espanol/news/author/gemma/] Si eres un desarrollador web, en algún momento necesitarás capturar información de las personas que usan tu sitio web o ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-agregar-un-formulario-netlify-a-una-aplicacion-react-creada-con-create-react-app/</link>
                <guid isPermaLink="false">614739c2fbc6fd08e90594ad</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Fri, 24 Sep 2021 12:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/09/question.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><strong><strong>Artículo original escrito por </strong></strong><a href="https://www.freecodecamp.org/news/author/joseph/">Joseph Mawa</a><br><strong><strong>Artículo original </strong></strong><a href="https://www.freecodecamp.org/news/how-to-add-a-netlify-form-to-a-react-app/">How to Add a Netlify Form to a React App Built with create-react-app</a><br><strong><strong>Traducido y adaptado por </strong></strong><a href="https://www.freecodecamp.org/espanol/news/author/gemma/">Gemma Fuster</a></p><p>Si eres un desarrollador web, en algún momento necesitarás capturar información de las personas que usan tu sitio web o aplicación.</p><p>Una forma de hacerlo es utilizando formularios HTML. Pero también hay muchos frameworks que puedes usar para crear aplicaciones web muy rápidamente.</p><p>Uno de estos frameworks es React. Puedes iniciar una aplicación de una sola página (SPA) muy fácilmente usando <code>create-react-app</code> (CRA). Después, puedes implementarla en plataformas como Netlify, Vercel, Firebase y Digital Ocean en un par de pasos.</p><p>El enfoque principal de este artículo será cómo agregar la funcionalidad de formulario de Netlify a una &nbsp;aplicación web React creada con <code>create-react-app</code>. Al final de este tutorial, podrás:</p><ul><li>Configurar una aplicación de una sola página rápidamente con <code>create-react-app</code></li><li>Añadir funcionalidad para utilizar la función de manejo de formularios incorporada de Netlify</li><li>Implementar la aplicación en Netlify</li><li>Configurar la función de manejo de formularios incorporada de Netlify para enviar notificaciones por correo electrónico cada vez que un cliente haya enviado un formulario</li></ul><p>Tanto si eres un principiante que intenta implementar su primera aplicación React como si eres un desarrollador de React experimentado, este artículo te ayudará a aprender a utilizar la funcionalidad de formulario incorporada de Netlify, sin escribir ningún código en el servidor.</p><p>Si eres un desarrollador de React experimentado, puedes saltarte la introducción e ir a <code>paso 6</code>. &nbsp;Si eres un principiante en React, puedes seguir este artículo desde el principio.</p><h2 id="prerrequisitos">Prerrequisitos</h2><p>Para seguir los pasos de este artículo, debes:</p><ul><li>Tener un conocimiento intermedio de JavaScript. Si eres un principiante, puedes seguir con el artículo y hacer preguntas en el foro de <a href="https://forum.freecodecamp.org/c/espanol/522">freeCodeCamp</a> en español si no entiendes algo. También puedes copiar los ejemplos de código en cada sección y jugar con ellos en tu editor de texto para entender lo que está pasando.</li><li>Tener al menos conocimientos básicos de la librería React.</li><li>Tener Node instalado en tu computadora.</li><li>Tener una cuenta de Netlify. Si no tienes una, puedes registrarte para obtener una cuenta gratis usando tu dirección de correo electrónico.</li><li>Tener un editor de texto como <a href="https://code.visualstudio.com/">VS code</a> o <a href="https://atom.io/">Atom</a> en tu computadora. Puedes probar los ejemplos de código a medida que avanzas. Te resultará más fácil de entender.</li></ul><h2 id="paso-1-comprueba-si-tienes-node-y-npm-instalados-en-tu-computadora">Paso 1: comprueba si tienes <strong><code>node</code> y <code>npm</code> instalados en tu computadora</strong></h2><p>Antes de comenzar, debes verificar si tienes <a href="https://nodejs.org/es/">node</a> (español) instalado en tu computadora.</p><p>Node es un entorno de ejecución de JavaScript, y es importante tenerlo instalado para poder ejecutar el proyecto. Abre una terminal y escribe lo siguiente en el símbolo del sistema.</p><pre><code class="language-js">node - v
</code></pre><p>En lugar de lo anterior, también puedes escribir esto. Ambos hacen lo mismo.</p><pre><code class="language-js">node --version
</code></pre><p>Si Node está instalado, deberías poder ver la versión en la terminal. Tu versión puede ser diferente a la mía, pero deberías ver algo como:</p><pre><code class="language-js">v15.13.0
</code></pre><p>Si Node está instalado, &nbsp;<code>npm</code> también está instalado porque las versiones nuevas de Node vienen con <code>npm</code>. Si tienes curiosidad, escribe <code>npm --version</code> o <code>npm -v</code>. Deberías poder ver la versión de <code>npm</code> que se ha instalado.</p><p>Por otra parte, si no tienes Node instalado, puedes descargarlo e instalarlo para tu plataforma <a href="https://nodejs.org/es/download/">aquí (español). </a></p><h2 id="paso-2-navega-hasta-el-directorio-donde-quieras-crear-tu-proyecto"><strong>Paso 2: </strong>Navega hasta el directorio donde quieras crear tu proyecto</h2><p>A continuación, debes navegar al directorio donde quieras crear tu proyecto. Puedes trabajar desde el escritorio o desde cualquier directorio que elijas.</p><p>A mí me gusta mantener mis proyectos en un directorio llamado <code>proyectos</code> en el mismo escritorio para tener un acceso más fácil. Esto es una preferencia personal.</p><p>Abre la terminal y navega hasta el directorio donde deseas crear tu proyecto. Yo uso <code>cd</code> (change directory) en los comandos a continuación.</p><p><strong>Toma nota</strong>: Yo ya tengo un directorio <code>proyectos</code> en mi escritorio. Si tú no lo tienes, tendrás que ejecutar <code>mkdir proyectos</code> antes de hacer <code>cd</code> para entrar en el directorio. Como he dicho antes, puedes trabajar desde otro directorio y tus comandos serán diferentes.</p><ol><li><code>cd Desktop</code></li><li><code>cd projects</code></li></ol><h2 id="paso-3-c-mo-crear-una-aplicaci-n-de-una-sola-p-gina-concreate-react-app"><strong>Paso 3: </strong>Cómo crear una aplicación de una sola página <strong>con<code>create-react-app</code></strong></h2><p>Vamos a crear un proyecto de React con <code>create-react-app</code>. En el directorio donde quieras tener la aplicación, ejecuta lo siguiente:</p><pre><code class="language-js">npx create-react-app netlify-form
</code></pre><p>Yo he nombrado a mi proyecto <code>netlify-form</code>. &nbsp; Tú puedes nombrarlo como desees.</p><p>Si no tienes <code>create-react-app</code> instalado, la terminal te preguntará si lo quieres instalar. Escribe <code>Y</code> en el símbolo del sistema &nbsp;(Y de "Yes"). &nbsp;Esto instalará <code>create-react-app</code> y luego creará un proyecto de React en el directorio <code>netlify-form</code>.</p><p>Si ya tienes <code>create-react-app</code> en tu sistema, creará el proyecto de React en el directorio <code>netlify-form</code>. Esto tardará un par de minutos, ten paciencia.</p><p>En el siguiente paso, empezarás con el servidor de desarrollo.</p><h2 id="paso-4-empezar-con-servidor-de-desarrollo"><strong>Paso 4: Empezar con servidor de desarrollo</strong></h2><p>En este paso, vamos a empezar con el servidor de desarrollo. Esto asegura la recarga automática cuando hacemos cambios en el proyecto durante el desarrollo, para que podamos ver cómo nuestro proyecto va tomando forma.</p><p>Puedes abrir el directorio <code>netlify-form</code> en el editor de texto que más te guste. Cuando estés en <code>netlify-form</code> (o el nombre que hayas escogido), abre la terminal y ejecuta:</p><pre><code class="language-js">npm run start
</code></pre><p>El comando anterior inicia el servidor de desarrollo en el puerto 3000. Si hay otro proyecto o servicio ejecutándose en el puerto 3000, se te pedirá que inicies el servidor en otro puerto.</p><p>Se abrirá una nueva pestaña del navegador en tu navegador predeterminado donde podrás ver el proyecto. Cualquier cambio que realices se reflejará automáticamente en el navegador.</p><p>En el siguiente paso, crearás un componente que contendrá tu formulario.</p><h2 id="paso-5-crea-un-componente-nuevo-dentro-del-directorio-src"><strong>Paso 5: Crea un componente nuevo dentro del directorio <code>src</code></strong></h2><p>Ahora vas a crear un componente llamado <code>Form</code> dentro del directorio <code>src</code>. En este componente, tendrás el formulario que se procesará en tu aplicación.</p><p>Crea un fichero <code>Form.js</code> en el directorio <code>src</code> y copia y pega el siguiente código:</p><pre><code class="language-js">import React from "react";

export default function Form() {
  return (
    &lt;form name="contact" method="post"&gt;
      &lt;p&gt;
        &lt;label htmlFor="name"&gt;Name&lt;/label&gt; &lt;br /&gt;
        &lt;input type="text" id="name" name="name" required /&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;label htmlFor="email"&gt;Email&lt;/label&gt; &lt;br /&gt;
        &lt;input type="email" id="email" name="email" required /&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;label htmlFor="message"&gt;Message&lt;/label&gt; &lt;br /&gt;
        &lt;textarea id="message" name="message" required&gt;&lt;/textarea&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;input type="submit" value="Submit message" /&gt;
      &lt;/p&gt;
    &lt;/form&gt;
  );
}
</code></pre><p>El componente anterior devuelve un simple formulario. He incluido cada par etiqueta-entrada y etiqueta-área de texto en su propia etiqueta <code>p</code>.</p><p>La etiqueta <code>p</code> no tiene nada de especial. Puedes usar <code>div</code> si lo prefieres. He usado <code>p</code> &nbsp;porque quiero aplicar espaciado entre los sucesivos pares etiqueta-entrada sin usar CSS.</p><p>Puedes importar el componente <code>Form</code> y ponerlo dentro de &nbsp;<code>App</code>. Para limpiar <code>App.js</code>, puedes eliminar algunos elementos que vienen con <code>create-react-app</code>, para que quede como esto:</p><pre><code class="language-js">import "./App.css";
import Form from "./Form";

function App() {
  return (
    &lt;div className="App"&gt;
      &lt;h1&gt; Get in touch &lt;/h1&gt;
      &lt;Form /&gt;
    &lt;/div&gt;
  );
}

export default App;
</code></pre><p>También puedes limpiar <code>App.css</code> para que solamente tenga el CSS:</p><pre><code class="language-css">.App {
  padding: 1em;
}
</code></pre><p>Cuando revises tu formulario en el navegador, debería aparecer como la siguiente imagen.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-from-2021-04-17-14-30-11.png" class="kg-image" alt="Screenshot-from-2021-04-17-14-30-11" width="600" height="400" loading="lazy"></figure><p>De momento, implementar esa aplicación en Netlify no nos permitirá capturar los envíos de formularios de un cliente. Para conseguirlo, necesitamos agregar la información necesaria a nuestra aplicación, para que los bots de Netlify puedan detectar nuestro formulario.</p><p>En el siguiente paso, vamos a agregar toda la información necesaria para hacer que el fichero de JSX <code>form</code> en React sea detectable para Netlify.</p><h2 id="paso-6-agregar-la-informaci-n-necesaria-para-que-form-sea-detectable-para-los-bots-de-netlify"><strong>Paso 6: Agregar la informaci</strong>ó<strong>n necesaria para que <code>form</code> sea detectable para los bots de &nbsp;Netlify</strong></h2><p>En este paso, agregarás información a tu aplicación para que Netlify pueda detectar la configuración del formulario de tu aplicación. Si tu formulario se implementa en HTML sin formato, el proceso para hacerlo detectable es muy sencillo. Puedes leer sobre esto en <a href="https://docs.netlify.com/forms/setup/?_ga=2.214149207.1369394306.1618461268-796209470.1617367540">documentaci</a>ó<a href="https://docs.netlify.com/forms/setup/?_ga=2.214149207.1369394306.1618461268-796209470.1617367540">n</a> (en inglés).</p><p>Pero si estás trabajando con un formulario JSX en React como en esta aplicación simple que estamos construyendo, tendrás que trabajar un poco más. Puede seguir los pasos que se describen a continuación.</p><h3 id="agrega-la-versi-n-html-del-formulario-al-fichero-index-html">Agrega la versión HTML del formulario al fichero<strong> <code>index.html</code> </strong></h3><p>Copia y pega los contenidos de tu fichero JSX form al fichero <code>index.html</code> justo después de la apertura de la etiqueta <code>body</code>. Esto asegurará que Netlify detecte nuestro formulario, porque los bots de compilación analizan los archivos HTML directamente en el momento de la implementación. Los bots no pueden analizar el formulario JSX.</p><p>Puedes quitar los elementos <code>label</code> y el elemento input &nbsp;<code>submit</code> porque añadiremos un atributo <code>hidden</code> a &nbsp;<code>form</code> para que no sea visible para los usuarios y lectores de pantalla.</p><p>Solamente puedes dejar los atributos <code>type</code> y <code>name</code> en los elementos &nbsp;<code>input</code> y el atributo <code>name</code> en <code>textarea</code> para que podamos mantener el formulario al mínimo.</p><p>Esto se ilustra en el código siguiente:</p><pre><code class="language-html">&lt;form name="contact" netlify netlify-honeypot="bot-field" hidden&gt;
     &lt;input type="text"  name="name"&gt;
     &lt;input type="email" name="email"&gt;
     &lt;textarea name="message"&gt;&lt;/textarea&gt;
&lt;/form&gt;
</code></pre><p>Como puedes ver en el fragmento de código anterior, tenemos los atributos adicionales <code>netlify</code> y <code>netlify-honeypot</code> en <code>form</code>. Los bots de Netlify los usarán mientras analizan tu HTML, así que asegúrate de agregarlos.</p><p>No te olvides del atributo <code>hidden</code>, porque este formulario debe estar oculto a los usuarios de tu sitio web. También vale la pena señalar que los atributos "name" en el formulario HTML deben ser exactamente los mismos que los del formulario JSX correspondiente.</p><h3 id="agrega-un-elemento-input-con-hidden-en-tu-jsx-form"><strong>Agrega un elemento <code>input</code> con "hidden" en tu JSX form</strong></h3><p>También necesitas agregar un elemento <code>input</code> con "hidden" en tu JSX <code>form</code> con los atributos <code>name</code> y <code>value</code> como se ilustra en el siguiente código:</p><pre><code class="language-html">&lt;input type="hidden" name="form-name" value="contact" /&gt;
</code></pre><p>El valor del atributo <code>name</code> siempre debe ser <code>"form-name"</code> y el valor del atributo <code>value</code> debe ser el nombre del formulario HTML, que en nuestro caso es <code>contact</code>.</p><p>Tu fichero <code>Form.js</code> debe tener:</p><pre><code class="language-js">import React from "react";

export default function Form() {
  return (
    &lt;form name="contact" method="post"&gt;
      &lt;input type="hidden" name="form-name" value="contact" /&gt;
      &lt;p&gt;
        &lt;label htmlFor="name"&gt;Name&lt;/label&gt; &lt;br /&gt;
        &lt;input type="text" id="name" name="name" required /&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;label htmlFor="email"&gt;Email&lt;/label&gt; &lt;br /&gt;
        &lt;input type="email" id="email" name="email" required /&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;label htmlFor="message"&gt;Message&lt;/label&gt; &lt;br /&gt;
        &lt;textarea id="message" name="message" required&gt;&lt;/textarea&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;input type="submit" value="Submit message" /&gt;
      &lt;/p&gt;
    &lt;/form&gt;
  );
}
</code></pre><p>Si ves la aplicación en el navegador, deberías poder ver el formulario –pero no podrás enviarlo desde tu configuración local. Solamente puedes enviar formularios después de implementar tu aplicación en Netlify.</p><p>Hagámoslo ahora.</p><h2 id="paso-7-implementa-la-aplicaci-n-en-netlify"><strong>Paso 7: </strong>Implementa la aplicación en Netlify</h2><p>En este paso, implementarás nuestra aplicación en Netlify para poder probar si los clientes pueden enviar formularios.</p><p>Hay un par de maneras de implementar tu aplicación en Netlify. Un método es compilar la aplicación localmente e implementarla con comandos en la terminal, otro es arrastrando y soltando la compilación de producción en Netlify. El segundo método consiste en configurar la implementación automática a través de GitHub, BitBucket o GitLab.</p><p>Para esta aplicación, la crearás localmente y utilizarás el método más simple de arrastrar y soltar. Este paso requiere que inicies una sesión en tu cuenta de Netlify. Si no tienes una cuenta, puedes registrarte para obtener una.</p><p>Ejecuta el comando <code>npm run build</code> en la terminal. Esto creará la aplicación para la producción en el directorio <code>build</code>. Esto llevará un poco de tiempo. Deberías poder ver el directorio <code>build</code> cuando el comando se haya ejecutado con éxito.</p><p>Inicia una sesión en tu cuenta de Netlify. En el panel de Netlify, haz clik en la opción de menú &nbsp;<code>Sites</code>. En la parte inferior de la página, hay un área donde puedes arrastrar y soltar la compilación de producción de tu aplicación. Después de arrastrar y soltar el directorio <code>build</code>, comienza el proceso de construcción (build).</p><p>Una vez que el sitio web se haya construido correctamente, puedes consultar el panel del proyecto para averiguar si Netlify está detectando tu formulario. Si está detectando el formulario, normalmente verás un mensaje indicándolo en la sección de formularios en la parte inferior izquierda.</p><p>Lo que queda por hacer es llenar el formulario y enviarlo. Después del envío, deberías poder ver la información enviada.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-from-2021-04-17-14-03-26.png" class="kg-image" alt="Screenshot-from-2021-04-17-14-03-26" width="600" height="400" loading="lazy"></figure><p>A continuación, aprenderemos cómo configurar alertas por correo electrónico para que recibas una notificación cada vez que un usuario envíe un formulario.</p><h2 id="paso-8-configura-actualizaciones-por-correo-electr-nico-cada-vez-que-un-usuario-env-e-un-formulario"><strong>Paso 8: </strong>Configura actualizaciones por correo electrónico cada vez que un usuario envíe un formulario</h2><p>En esta sección, configurarás tu aplicación para enviar notificaciones por correo electrónico a una dirección de correo electrónico cada vez que se envíe un formulario.</p><p>Para ello, navega hasta la configuración del sitio web. A la izquierda, verás una lista de opciones del menú. Haz click en la opción <code>forms</code>.</p><p>Bajo <code>outgoing notifications</code>, haz clik en <code>Add notification</code> y selecciona la opción &nbsp;<code>Email notification</code>. A continuación, configurarás tus preferencias como prefieras.</p><figure class="kg-card kg-image-card kg-width-full"><img src="https://www.freecodecamp.org/news/content/images/2021/04/Screenshot-from-2021-04-17-14-11-20.png" class="kg-image" alt="Screenshot-from-2021-04-17-14-11-20" width="600" height="400" loading="lazy"></figure><p>Eso es todo lo que necesitas para utilizar la funcionalidad de formulario integrada de Netlify con CRA. No necesitas código en un servidor para obtener comentarios de tus clientes.</p><p>Si has logrado seguir con éxito los pasos anteriores, ¡enhorabuena! Ahora puedes seguir adelante y explorar otras funciones.</p><p>Si encuentras errores o problemas relacionados con los formularios de Netlify mientras sigues este tutorial, no dudes en consultar <a href="https://answers.netlify.com/t/support-guide-form-problems-form-debugging-404-when-submitting/92">netlify form error debugging tip (depuración de errores de formulario de netlify, en inglés).</a></p><p>También puedes leer <a href="https://docs.netlify.com/forms/setup/">netlify forms documentation</a> (inglés).</p><p>Si no encuentras una solución después de utilizar los recursos anteriores, puedes preguntar en <a href="https://answers.netlify.com/">netlify forum</a> (inglés). En esa comunidad hay muchas personas amables que podrían ayudarte.</p><h2 id="conclusi-n">Conclusión</h2><p>En este artículo, hemos analiza:</p><ul><li>Cómo crear una aplicación React usando <code>create-react-app</code></li><li>Cómo agregar un formulario en JSX &nbsp;a tu aplicación React</li><li>Cómo agregar la información necesaria para que los bots de Netlify puedan detectar tu formulario</li><li>Cómo implementar una compilación de producción en Netlify</li><li>Cómo configurar notificaciones por correo electrónico cada vez que un cliente envíe un formulario</li></ul><h3 id="references"><strong>References</strong></h3><ul><li><a href="https://docs.netlify.com/forms/setup/">Netlify forms documentation</a> (inglés)</li><li><a href="https://create-react-app.dev/">Create react app documentation</a> (inglés)</li><li><a href="https://es.reactjs.org/">React documentation</a> (español)</li><li><a href="https://answers.netlify.com/t/support-guide-form-problems-form-debugging-404-when-submitting/92">Netlify form error debugging</a> (inglés)</li></ul><p> </p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ ¿Qué significa "this" en JavaScript? La palabra clave "this" explicada con ejemplos ]]>
                </title>
                <description>
                    <![CDATA[ Artículo original escrito por Kingsley Ubah [https://www.freecodecamp.org/news/author/ubahthebuilder/] Artículo original: The this Keyword Explained with Examples [https://www.freecodecamp.org/news/what-is-this-in-javascript/] Traducido y adaptado por: GEMMA FUSTER [/espanol/news/author/gemma/] Para comprender lo que significa realmente this en JavaScript, echemos un vistazo a un concepto muy similar en el idioma inglés: la polisemia. Consideremos la palabra "run". ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/que-significa-this-en-javascript-la-palabra-clave-this-explicada-con-ejemplos/</link>
                <guid isPermaLink="false">61191f623e80820908da4d57</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Mon, 16 Aug 2021 01:53:43 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/08/this-js.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><strong><strong><strong><strong><strong><strong><strong><strong>Artículo original escrito por</strong></strong></strong></strong> </strong></strong></strong></strong><a href="https://www.freecodecamp.org/news/author/ubahthebuilder/">Kingsley Ubah</a><br><strong><strong><strong><strong>Art</strong></strong></strong></strong><strong><strong><strong><strong><strong><strong><strong><strong>í</strong></strong></strong></strong></strong></strong></strong></strong><strong><strong><strong><strong>culo original:</strong></strong> </strong></strong><a href="https://www.freecodecamp.org/news/what-is-this-in-javascript/">The this Keyword Explained with Examples</a><br><strong><strong><strong><strong>Traducido y adaptado por: </strong></strong></strong></strong><a href="https://www.freecodecamp.org/espanol/news/author/gemma/">GEMMA FUSTER</a></p><p>Para comprender lo que significa realmente <code>this</code> en JavaScript, echemos un vistazo a un concepto muy similar en el idioma inglés: la polisemia.</p><p>Consideremos la palabra "run". "Run" es una sola palabra que puede significar muchas cosas diferentes según el contexto.</p><ul><li>“I will run home” – "Correré a casa": significa moverse rápidamente a pie</li><li>“She ran the 1500m” – Ella corrió los 1500 m" - significa correr en una carrera</li><li>“He is running for president” – "Se presenta a presidente". &nbsp;Significa que quiere un puesto oficial.</li><li>“The app is running” – "La aplicación se está ejecutando": significa que la aplicación de software aún está abierta y activa.</li><li>“Go for a run” – "Sal a correr": significa correr como una forma de ejercicio.</li></ul><p><em>Y la lista continua<em>.</em></em></p><p>Ocurre algo similar con el uso de la palabra clave <code><strong><strong>this</strong></strong></code><em><em><strong><strong> </strong></strong></em></em> en tu código de JavaScript. Cuando lo haces, se resuelve automáticamente en un objeto o enlace según el contexto en el que se definió.</p><p>¿Cuáles son los posibles contextos? ¿Y cómo podemos usar esa información para deducir a qué objeto se referirá una llamada con &nbsp;<strong><strong><code>this</code></strong></strong>?</p><h2 id="contexto-this"><strong>Contexto <code>this</code> </strong></h2><p>Cuando se usa en una función, <code>this</code> simplemente apunta a un objeto al que está vinculado. Responde a la pregunta "<strong>de dónde debería obtener algún valor o datos</strong>":</p><pre><code class="language-js">function alert() { 
  console.log(this.nombre + ' esta llamando'); 
}
</code></pre><p>En la función anterior, la palabra clave <code>this</code> se refiere a un objeto al que está vinculado <strong>y <strong> </strong>obtiene la propiedad <strong>"n</strong>ombre<strong>" </strong>de allí</strong>.</p><p>Pero, ¿cómo saber a qué objeto está vinculada la función? ¿Cómo averiguas a qué se refiere <code>this</code>?</p><p>Para hacerlo, necesitamos echar un vistazo detallado a cómo las funciones están vinculadas a los objetos.</p><h2 id="tipos-de-enlaces-en-javascript">Tipos de enlaces en JavaScript</h2><p>Por lo general, existen cuatro tipos de enlaces:</p><ul><li>Por defecto (predeterminada)</li><li>implícito</li><li>explícito</li><li>de constructor</li></ul><h2 id="enlace-por-defecto-en-javascript">Enlace por defecto en JavaScript</h2><p>Una de las primeras reglas que hay que recordar es que si la función que contiene esta referencia &nbsp;<code>this</code> es una <strong>función independiente</strong>, esa función está vinculada al <strong>objeto global</strong>.</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">function alert() { 
  console.log(this.nombre + ' esta llamando'); 
}

const nombre = 'Kingsley'; 
alert(); // Kingsley esta llamando
</code></pre><figcaption>Función independiente</figcaption></figure><p>Como puedes ver, <code>nombre()</code> es una función independiente y no adjunta a un objeto, por lo que está vinculada al ámbito <strong>global</strong>. &nbsp;Como resultado, la referencia <code>this.nombre</code> se resuelve en la variable global <strong><strong><code>const n</code></strong><code>ombre</code><strong><code> = 'Kingsley'</code></strong></strong>.</p><p>Sin Embargo, esta regla no se cumple si <code>nombre()</code> se definiera en modo estricto (strict mode):</p><figure class="kg-card kg-code-card"><pre><code class="language-js">function alert() { 
  'use strict'; 
  console.log(this.nombre + ' esta llamando'); 
}

const nombre = 'Kingsley'; 
alert(); // TypeError: `this` is `undefined`
</code></pre><figcaption>undefined en mode estricto</figcaption></figure><p>Cuando se establece como "strict mode", &nbsp;<code>this</code> es "undefined".</p><h2 id="enlace-impl-cito-en-javascript">Enlace implícito en JavaScript</h2><p>Otro escenario a tener en cuenta es si la función está adjunta a un objeto (su contexto) cuando se la llama.</p><p>De acuerdo con la regla de vinculación en JavaScript, una función puede usar un objeto como contexto solo si ese objeto está vinculado a él en la llamada. Esta forma de vinculación se conoce como vinculación implícita.</p><p>Esto es lo que quiero decir:</p><pre><code class="language-js">function alert() { 
  console.log(this.edad + ' anyos'); 
}

const miObjecto = {
  edad: 22,
  alert: alert
}

miObjeto.alert() // 22 anyos
</code></pre><p>Sencillamente, cuando llamas a una función usando el punto, <code>this</code> está implícitamente vinculado al objeto desde el que se llama a la función.</p><p>En este ejemplo, dado que <code>alert</code> es llamada desde &nbsp;<code>miObjeto</code>, la palabra clave <code>this</code> está vinculada a &nbsp;<code>miObjeto</code>. &nbsp;Cuando llamamos a <code>alert</code> con <code>miObjeto.alert()</code>, <code>this.edad</code> es 22, siendo &nbsp;<code>edad</code> una propiedad de <code>miObjeto</code>.</p><p>Veamos otro ejemplo:</p><pre><code class="language-js">function alert() { 
  console.log(this.edad + ' anyos'); 
}

const miObjeto = {
  edad: 22,
  alert: alert,
  anidacionObj: {
    edad: 26,
    alert: alert
  }
}

miObjeto.anidacionObj.alert(); // 26 anyos</code></pre><p>Aquí, ya que a <code>alert</code> se la llama desde <code>anidacionObj</code>, <code>this</code> está implícitamente vinculada a &nbsp;<code>anidacionObj</code> en lugar de <code>miObjeto</code>.</p><p>Una manera fácil de averiguar a qué objeto está implícitamente vinculado <code>this</code> &nbsp;es mirar qué objeto está a la izquierda del punto (.):</p><pre><code class="language-js">function alert() { 
  console.log(this.edad + ' anyos'); 
}

const miObjeto = {
  edad: 22,
  alert: alert,
  anidacionObj: {
    edad: 26,
    alert: alert
  }
}

miObjeto.alert(); // `this` vinculada a `miObjeto` -- 22 anyos
miObjeto.anidacionObj.alert(); // `this` vinculada a `anidacionObj` -- 26 anyos</code></pre><p><strong>Enlace explícito en JavaScript</strong></p><p>Hemos visto que la vinculación implícita &nbsp;tiene que ver con la relación con un objeto.</p><p>Pero, ¿qué pasa si queremos <strong>forzar </strong>a una función a usar un objeto como contexto sin poner una referencia de función de propiedad en el objeto? </p><p>Tenemos dos métodos para lograr esto: <code>call()</code> y <code>apply()</code>.</p><p>Junto con un par de otros conjuntos de funciones de utilidad, estas dos utilidades están disponibles para todas las funciones en JavaScript a través del mecanismo [[Prototype]].</p><p>Para vincular explícitamente una llamada de función a un contexto, simplemente tienes que invocar la llamada () en esa función y pasar el objeto de contexto como parámetro:</p><pre><code class="language-js">function alert() { 
  console.log(this.edad + ' anyos'); 
}

const miObjeto = {
  edad: 22
}

alert.call(miObjeto); // 22 anyos</code></pre><p>Y aquí está la parte divertida. Incluso si tuvieras que pasar esa función varias veces a nuevas variables (currying), cada invocación usará el mismo contexto porque se ha unido (vinculado explícitamente) a ese objeto. Esto se llama <strong>vinculación dura</strong>. </p><figure class="kg-card kg-code-card"><pre><code class="language-js">function alert() { 
  console.log(this.edad); 
} 

const miObjeto = { 
  edad: 22 
}; 

const bar = function() { 
  alert.call(miObjeto); 
}; 

bar(); // 22
setTimeout(bar, 100); // 22 
// una `bar` con vinculacion dura ya no puede tener su `this` cambiado 
bar.call(window); // sigue siendo 22
</code></pre><figcaption>vinculacion dura</figcaption></figure><p>El enlace o vinculación dura es una forma perfecta de unir un contexto en una llamada de función y convertir realmente esa función en un método.</p><h3 id="enlace-de-constructor-en-javascript"><strong>Enlace de Constructor en JavaScript</strong></h3><p>El tipo de enlace final y quizás más interesante es el nuevo enlace que también acentúa el comportamiento inusual de JavaScript en comparación con otros lenguajes basados en clases.</p><p>Cuando se invoca una función con la palabra clave &nbsp;<code>new</code>, también conocida como <strong>llamada de constructor</strong>, ocurre lo siguiente:</p><ol><li>Se crea (o construye) un objeto nuevo</li><li>El objeto recién construido es vinculado a &nbsp;[[Prototype]] a la función que lo construyó</li><li>El objeto recién construido se establece como enlace <code>this</code> para esa llamada de función.</li></ol><p>Veamos esto en el código para comprenderlo mejor:</p><pre><code class="language-js">function darEdad(edad) { 
  this.edad = edad; 
} 

const bar = new darEdad(22); 
console.log(bar.edad); // 22</code></pre><p>Al llamar <code>darEdad(...)</code> con <code>new</code>, hemos creado un objeto nuevo y configurado ese object nuevo como &nbsp;<code>this</code> para la llamada <code>bar(...)</code>. Entonces <code>new</code> es la última forma en la que puede vincular &nbsp;<code>this</code> &nbsp;en la llamada a una función.<br></p><h2 id="para-terminar">Para terminar</h2><ul><li>La palabra clave <code>this</code>, cuando se usa en una función, enlaza la función con el contexto del objeto.</li><li>Hay 4 tipos de enlaces: <em>por defecto<em>, impl</em>íci<em>t</em>o<em>, expl</em>í<em>c</em>i<em>t</em>o<em> </em>y<em> </em>de <em>constructor </em></em>(<em><em>new</em></em>)</li><li>Conocer estas 4 reglas te ayudará a discernir el contexto de una referencia con &nbsp;<code>this</code>.</li></ul><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2021/08/image-3.png" class="kg-image" alt="image-3" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2021/08/image-3.png 600w, https://www.freecodecamp.org/espanol/news/content/images/2021/08/image-3.png 1000w" sizes="(min-width: 720px) 720px" width="1000" height="847" loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2021/08/image-4.png" class="kg-image" alt="image-4" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2021/08/image-4.png 600w, https://www.freecodecamp.org/espanol/news/content/images/2021/08/image-4.png 1000w" sizes="(min-width: 720px) 720px" width="1000" height="834" loading="lazy"></figure><p>Si te ha gustado o beneficiado mi artículo y me quieres apoyar, me puedes comprar un café <a href="https://buymeacoffee.com/ubahthebuilder">aquí</a>. </p><p>También me puedes encontrar en <a href="https://twitter.com/UbahTheBuilder">Twitter</a>. Visita mi <a href="https://ubahthebuilder.tech/">blog</a> para más contenido sobre JavaScript &nbsp;y programación. </p><p>Gracias y nos vemos.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo usar Async / Await para escribir un código mejor en JavaScript ]]>
                </title>
                <description>
                    <![CDATA[ Hay una sintaxis especial que puedes usar en JavaScript y que te facilita el trabajo con promesas. Se llama "async / await" y es sorprendentemente fácil de entender y usar. En este artículo, hablaré de:  1. ¿Qué son las funciones asíncronas?  2. Cómo funcionan las promesas en JavaScript ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-usar-async-await-para-escribir-un-codigo-mejor-en-javascript/</link>
                <guid isPermaLink="false">6106f4f2bd9dff09271bebc9</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Tue, 03 Aug 2021 05:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/08/Blue-and-White-Syringe-Corporate-Clean-Vaccine-Information-General-Health-Banner-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hay una sintaxis especial que puedes usar en JavaScript y que te facilita el trabajo con promesas. Se llama "async / await" y es sorprendentemente fácil de entender y usar.</p><p>En este artículo, hablaré de:</p><ol><li>¿Qué son las funciones asíncronas?</li><li>Cómo funcionan las promesas en JavaScript</li><li>Conceptos básicos de Async / Await</li><li>Cómo usar async / await con manejo de errores</li><li>Cómo una función asíncrona devuelve una promesa</li><li>Cómo utilizar <code>promise.all()</code></li></ol><p>Así que vamos allá</p><h2 id="-qu-son-las-funciones-as-ncronas">¿Qué son las funciones asíncronas?</h2><p>El término asíncrono se refiere a una situación en la que dos o más eventos no ocurren al mismo tiempo. O en términos más sencillos, pueden suceder varias cosas relacionadas sin esperar a que se complete la acción anterior.</p><p>En JavaScript, <strong>las funciones asíncronas</strong> son muy importantes debido a la naturaleza de <strong>un solo subproceso de JavaScript</strong>. Con la ayuda de funciones asíncronas, el bucle de eventos de JavaScript puede encargarse de otras cosas cuando la función solicita algún otro recurso.</p><p>Usarías un código asíncrono, por ejemplo, en las API que obtienen un archivo de la red, cuando accedes a una base de datos y devuelves datos de ella, cuando accedes a una transmisión de video desde una cámara web, o si estás transmitiendo la pantalla a un headset de realidad virtual.</p><h2 id="c-mo-funcionan-las-promesas-en-javascript">Cómo funcionan las promesas en JavaScript</h2><p>El objeto <strong><strong><code>Promise</code></strong> </strong>en JavaScript representa una operación asíncrona (y su valor resultante) que eventualmente se completará (o fallará).</p><p>Una <strong><strong><code>Promise</code></strong> </strong>puede estar en uno de estos estados:</p><ul><li><em><em>pending</em> <em>(pendiente)</em></em>: estado inicial, ni cumplida ni rechazada.</li><li><em><em>fulfilled</em> (cumplida)</em>: significa que la operación se completó con éxito.</li><li><em><em>rejected</em> (rechazada)</em>: significa que la operación falló.</li></ul><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2021/08/image.png" class="kg-image" alt="image" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2021/08/image.png 600w, https://www.freecodecamp.org/espanol/news/content/images/size/w1000/2021/08/image.png 1000w, https://www.freecodecamp.org/espanol/news/content/images/size/w1600/2021/08/image.png 1600w, https://www.freecodecamp.org/espanol/news/content/images/2021/08/image.png 2000w" sizes="(min-width: 720px) 720px" width="2000" height="1044" loading="lazy"></figure><p>La función que se pasa a una nueva promesa se llama ejecutora. Sus argumentos (<code>resolve</code> y<code>reject</code>) se denominan callbacks y los proporciona JavaScript. Cuando el ejecutor obtiene el resultado, ya sea ahora o más tarde, debe llamar a una de estas callbacks.</p><p>Aquí va un ejemplo de una promesa:</p><pre><code class="language-js">const miPromesa = new Promise(function(resolve, reject) =&gt; {
  setTimeout(() =&gt; {
    resolve('foo');
  }, 300);
});</code></pre><p>Y aquí van ejemplos de una promesa cumplida frente a una promesa rechazada:</p><pre><code class="language-js">// promesa cumplida
let  promesa = new  Promise(function(resolve, reject) {
 setTimeout(()  =&gt; resolve(new Error("Hecho!")), 1000);
});

// resolve ejecuta la primera funcion en .then
promesa.then(
  result =&gt; alert(result), // Muestra "hecho!" depues de 1 segundo
  error =&gt; alert(error) // no se ejecuta
);</code></pre><pre><code class="language-js">// promesa rechazada
let promesa =  new  Promise(function(resolve, reject)  { 
 setTimeout(()  =&gt; reject(new Error("Whoops!")), 1000);
});

// reject ejecuta la segunda funcion en .then
promesa.then(
  result =&gt; alert(result), // No se ejecuta
  error =&gt; alert(error) // Muestra "Error: Whoops!" despues de 1 segundo
);</code></pre><h2 id="conceptos-b-sicos-de-async-await-en-javascript">Conceptos básicos de Async / Await en JavaScript</h2><p>Tenemos dos partes cuando usamos <code>async/await</code> en nuestro código.</p><p>En primer lugar, tenemos la palabra clave <code>async</code> , que se pone delante de una declaración de función para convertirla en una función async.</p><p>Una función asíncrona es una función que sabe que es posible que se use la palabra clave &nbsp;<code>await</code> dentro de ella para invocar código asíncrono.</p><p><em>La palabra clave </em><code><em>async</em></code><em> se añade a las funciones para que devuelvan una promesa en lugar de un valor directamente.</em></p><pre><code class="language-jsx">const cargarDatos = async () =&gt; {
  const url = "https://jsonplaceholder.typicode.com/todos/1";
  const res = await fetch(url);
  const datos = await res.json();
  console.log(datos);
};
cargarDatos();</code></pre><pre><code class="language-jsx">// output en la consola
{
  completed: false,
  id: 1,
  title: "delectus aut autem",
  userId: 1
}</code></pre><h2 id="c-mo-usar-async-await-con-manejo-de-errores">Cómo<strong> usar Async/Await </strong>con manejo de errores</h2><p>Podemos manejar errores usando un bloque try catch como este: </p><pre><code class="language-jsx">const cargarDatos = async () =&gt; {
  try{
	  const url = "https://jsonplaceholder.typicode.com/todos/1";
	  const res = await fetch(url);
	  const datos = await res.json();
	  console.log(datos);
  } catch(err) {
    console.log(err)
  }
};

cargarDatos();</code></pre><p>El try-catch anterior solamente manejará errores al obtener los datos, como una sintaxis incorrecta, nombres de dominio incorrectos, errores de red, etc.</p><p>Cuando quieras manejar un mensaje de error del código de respuesta de la API, puedes usar <code>res.ok</code> ( <code>res</code> es la variable en la que se almacena la respuesta). Te dará un Boolean con el valor verdadero si el código de respuesta está entre 200 y 209. </p><pre><code class="language-jsx">const cargarDatos = async () =&gt; {
  try{
	  const url = "https://jsonplaceholder.typicode.com/todos/qwe1";
	  const res = await fetch(url);
	  if(res.ok){ 
	    const datos = await res.json();
	    console.log(datos);
	  } else {
	    console.log(res.status); // 404
	  }
  } catch(err) {
    console.log(err)
  }
};

cargarDatos();

// OUTPUT
// 404</code></pre><h2 id="c-mo-una-funci-n-async-devuelve-una-promesa">Cómo una función Async devuelve una promesa </h2><p>Este es uno de los rasgos de las funciones asíncronas — se garantiza que sus valores de retorno se convertirán en promesas. Para manejar los datos devueltos por una función <code>async</code> podemos usar una palabra clave <code>then</code> para obtener los datos.</p><pre><code class="language-jsx">const cargarDatos = async () =&gt; {
  try{
    const url = "https://jsonplaceholder.typicode.com/todos/1";
    const res = await fetch(url);
    const datos = await res.json();
    return datos
  } catch(err) {
    console.log(err)
  }
};

const datos = cargarDatos().then(datos =&gt; console.log(datos));</code></pre><p><strong><strong>? PRO TIP :</strong></strong><br>Si quieres usar un <code>async-await</code> para manejar los datos devueltos puedes utilizar un IIFE, pero solo está disponible en Node 14.8 o superior.</p><pre><code class="language-jsx">// usa una IIFE asincrona 
(async () =&gt; {
  const datos = await cargarDatos();
  console.log(datos);
})();</code></pre><p><code>await</code> solo funciona dentro de funciones asíncronas en JavaScript normal. Pero puede usarlo por sí misma con <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Modules">módulos JavaScript</a>. </p><h2 id="c-mo-usar-promise-all-en-javascript">Cómo usar Promise.all () en JavaScript</h2><p><code>Promise.all()</code> es muy útil cuando queremos llamar a varias APIs.</p><p>Utilizando una función con <code>await</code> de manera tradicional, tenemos que esperar a que se complete cada solicitud antes de pasar a la siguiente. Esto puede ser un problema cuando cada solicitud tarda en completarse. Esto puede hacer que la respuesta sea muy lenta.</p><p>Usando <code>Promise.all()</code>, podemos llamar a cada una de estas API en paralelo. (Esto es una explicación muy básica &nbsp;– Para una explicación más detallada consulta <a href="https://anotherdev.xyz/promise-all-runs-in-parallel/#:~:text=all%20doesn't%20guarantee%20you,are%20done%20with%20their%20job.">este </a>estupendo artículo) .</p><p><em>Ten cuidado cuando uses </em><code><em>Promise.all()</em></code><em>, – si una de las solicitudes con await falla, todo el .all() falla.</em></p><pre><code class="language-js">const cargarDatos = async () =&gt; {
  try{
    const url1 = "https://jsonplaceholder.typicode.com/todos/1";
    const url2 = "https://jsonplaceholder.typicode.com/todos/2";
    const url3 = "https://jsonplaceholder.typicode.com/todos/3";
    const resultados = await Promise.all([
      fetch(url1),
      fetch(url2),
      fetch(url3)
    ]);
    const promesasDeDatos = await resultados.map(result =&gt; result.json());
    const datosFinales = Promise.all(promesasDeDatos);
    return datosFinales
  } catch(err) {
    console.log(err)
  }
};

const datos = cargarDatos().then(datos =&gt; console.log(datos));</code></pre><pre><code class="language-jsx">// output en la consola
[{
  completed: false,
  id: 1,
  title: "delectus aut autem",
  userId: 1
}, {
  completed: false,
  id: 2,
  title: "quis ut nam facilis et officia qui",
  userId: 1
}, {
  completed: false,
  id: 3,
  title: "fugiat veniam minus",
  userId: 1
}]</code></pre><h2 id="conclusi-n">Conclusión</h2><p>En la mayoría de las situaciones, podemos usar <code>async/await</code> con un bloque <code>try catch</code> para manejar tanto los resultados como los errores.</p><p>Por el momento, <code>await</code> no funcionará en el código al nivel superior. Esto quiere decir que si estamos fuera de una función asíncrona (<code>async</code> ), no podemos usar &nbsp;<code>await</code> sintácticamente. En este caso, lo habitual es agregar <code>.then/catch</code> para manejar el resultado final o el error.</p><p><em>A nivel superior en el </em>código<em> , <code>await</code> </em>está <em>disponible en Node.js <code>v14.8</code> o superior y solamente en módulos ES. Puedes ver </em>más aquí<em>: <a href="https://www.stefanjudis.com/today-i-learned/top-level-await-is-available-in-node-js-modules/#top-level-%60await%60-is-available-%22unflagged%22-in-node.js-since-%60v14.8%60">Top-level await is available in Node.js modules | Stefan Judis Web Development</a></em></p><h3 id="recursos-que-me-han-ayudado"><strong>Recursos que me han ayudado</strong></h3><ul><li><a href="https://javascript.info/promise-basics">Promises (javascript.info)</a></li><li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript - Learn web development | MDN (mozilla.org)</a></li><li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise - JavaScript | MDN (mozilla.org)</a></li></ul><h2 id="antes-de-terminar-"><strong>Antes de terminar...</strong></h2><p>? ¿Quieres escribir código &nbsp;y aprender conmigo? Puede encontrar el mismo contenido aquí en mi <a href="https://milindsoorya.site/">blog</a>. Simplemente abre tu editor de código favorito y empieza.</p><p><a href="https://milindsoorya.site/">Milind Soorya:</a></p><p><a href="https://milindsoorya.site/">Soy Milind. Soy un full-stack developer y blogger. En este sitio web exploramos estrategias y herramientas que nos ayudan a escribir un </a>código <a href="https://milindsoorya.site/">mejor y </a>más <a href="https://milindsoorya.site/">limpio.</a><br></p><p>Vamos a conectar. Puedes seguirme en <a href="https://twitter.com/milindsoorya">Twitter (@milindsoorya)</a> donde estoy muy activo. </p><p>Traducido del artículo de <a href="https://www.freecodecamp.org/news/author/milind/">Milind Soorya</a> - <a href="https://www.freecodecamp.org/news/how-to-use-async-await-write-better-javascript/">How to Use Async/Await to Write Better JavaScript Code</a></p><p></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tutorial de cláusula de JavaScript: cómo funcionan las cláusulas y el ámbito (scope) léxico en JS ]]>
                </title>
                <description>
                    <![CDATA[ En JavaScript, la gente a menudo confunde las cláusulas con el ámbito léxico. El ámbito léxico es una parte importante de las cláusulas, pero no es una cláusula en sí mismo. Las cláusulas son un concepto avanzado y un tema frecuente en entrevistas técnicas. Debes tener un conocimiento básico de ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/tutorial-de-clausulas-de-javascript-como-funcionan-los-clausulas-y-el-ambito-lexico-en-js/</link>
                <guid isPermaLink="false">60e0ea84ce2597091235e681</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Mon, 12 Jul 2021 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/07/FCC-closures-article.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>En JavaScript, la gente a menudo confunde las cláusulas con el ámbito léxico.</p><p>El ámbito léxico es una parte importante de las cláusulas, pero no es una cláusula en sí mismo.</p><p>Las cláusulas son un concepto avanzado y un tema frecuente en entrevistas técnicas.</p><p>Debes tener un conocimiento básico de las funciones antes de intentar entender las cláusulas.</p><p>Después de leer este artículo, espero haberte ayudado a aprender lo siguiente:</p><ul><li>La diferencia entre ámbito léxico y cláusulas.</li><li>Por qué las cláusulas requieren un ámbito léxico.</li><li>Cómo dar un ejemplo de cláusulas durante una entrevista de trabajo.</li></ul><h2 id="-qu-es-el-mbito-l-xico-en-javascript">¿Qué es el ámbito léxico en JavaScript?</h2><p>El ámbito léxico describe cómo las funciones anidadas (también conocidas como "secundarias") tienen acceso a las variables definidas en los ámbitos de sus padres.</p><pre><code class="language-js">const miFuncion = () =&gt; {
     let miValor = 2;
     console.log(miValor);

     const funcionHija = () =&gt; {
          console.log(miValor += 1);
     }

     funcionHija();
}

miFuncion();</code></pre><p>En este ejemplo, <code>funcionHija</code> tiene acceso a la variable <code>miValor</code> que está definida en el ámbito de la función padre &nbsp;<code>miFuncion</code>.</p><p>El ámbito léxico de <code>funcionHija</code> permite el acceso al ámbito del padre (función madre).</p><h2 id="-qu-es-una-cl-usula-en-javascript">¿Qué es una<strong><strong> </strong></strong>cláusula<strong><strong> </strong>e<strong>n JavaScript?</strong></strong></h2><p><a href="https://www.w3schools.com/js/js_function_closures.asp">w3Schools.com</a> ofrece una gran definición de lo que es una cláusula:</p><blockquote>Una cláusula es una función que tiene acceso al ambito de su función padre, incluso después de que la función padre haya terminado de ejecutar.</blockquote><p>Observemos la primera parte de la oración, antes de la coma:</p><blockquote>...una función que tiene acceso al ambito de su padre</blockquote><p>¡Eso describe el ámbito léxico!</p><p>Pero necesitamos la segunda parte de la definición para tener un ejemplo de una cláusula...</p><blockquote>...incluso después de que la función padre haya terminado de ejecutar.</blockquote><p>Veamos un ejemplo de una cláusula:</p><pre><code class="language-js">const miFuncion = () =&gt; {
     let miValor = 2;
     console.log(miValor);

     const funcionHija = () =&gt; {
          console.log(miValor += 1);
     }

     return funcionHija;
}

const resultado = miFuncion();
console.log(resultado);
resultado();
resultado();
resultado();</code></pre><p>Copia el código del ejemplo anterior y pruébalo.</p><p><em>Analicemos lo que está pasando<em>...</em></em></p><p>En esta versión, <code>miFuncion</code> devuelve <code>funcionHija</code> en lugar de llamarla.</p><p>Por tanto, cuando a <code>resultado</code> &nbsp;se le asigna <code>miFuncion()</code>, la instrucción en la consola dentro de <code>miFuncion</code> es registrada, pero no la instrucción dentro de &nbsp;<code>funcionHija</code>.</p><p><code>funcionHija</code> no es ejecutada.</p><p>En lugar de eso, es devuelta y guardada en <code>resultado</code>.</p><p>Además, debemos darnos cuenta de que <code>miFuncion</code> ha terminado de ejecutarse.</p><p>La línea con <code>console.log(resultado)</code> debe mostrar en la consola que <code>resultado</code> ahora contiene el valor de la función anónima que es<code>funcionHija</code>.</p><p>Ahora, cuando ejecutamos <code>resultado()</code>, estamos llamando a la función anónima que es <code>funcionHija</code>.</p><p>Como hija de <code>miFuncion</code>, esta función anónima tiene acceso a la variable <code>miValor</code> dentro de <code>miFuncion</code> ¡<em>incluso </em>después<em><em> </em>de que haya terminado su <em>ejecución!</em></em></p><p>La cláusula que creamos, ahora nos permite continuar aumentando el valor de la variable <code>miValor</code> &nbsp;cada vez que ejecutamos <code>resultado()</code>.</p><h2 id="t-mate-tu-tiempo-con-cl-usulas">Tómate tu tiempo con cláusulas</h2><p>Las cláusulas se consideran un concepto avanzado con motivo.</p><p>Incluso con un desglose paso a paso de lo que es una cláusula, entender este concepto puede llevar tiempo.</p><p>No te apresures para entenderlo y no seas duro contigo mismo si no tiene sentido al principio.</p><p>Cuando entiendas completamente las cláusulas, es posible que sientas lo que sintió <a href="https://www.google.com/search?q=neo+sees+the+matrix&amp;source=lnms&amp;tbm=isch&amp;sa=X&amp;ved=2ahUKEwiG1MaN1rPxAhUNCM0KHQJWCtAQ_AUoAXoECAEQAw&amp;biw=1762&amp;bih=886">Neo cuando vio la Matri</a>z. ¡Verás nuevas posibilidades de código y te darás cuenta de que estuvieron ahí todo el tiempo!</p><p>Te dejo con un tutorial sobre cláusulas de <a href="https://www.youtube.com/davegrayteachescode">mi canal de YouTube</a>. Profundizo un poco más y proporciono algunos ejemplos más de cláusulas para aprovechar la discusión en este artículo.</p><figure class="kg-card kg-embed-card" data-test-label="fitted">
        <div class="fluid-width-video-container">
          <div style="padding-top: 56.17837837837838%;" class="fluid-width-video-wrapper">
            <iframe src="https://www.youtube.com/embed/1S8SBDhA7HA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" name="fitvid0" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 22px; vertical-align: middle; position: absolute; top: 0px; left: 0px; width: 740px; height: 415.72px;"></iframe>
          </div>
        </div>
      </figure><p>Traducido del artículo de &nbsp;<a href="https://www.freecodecamp.org/news/author/dave/">Dave Gray</a> <strong>- </strong><a href="https://www.freecodecamp.org/news/javascript-closure-lexical-scope/">JavaScript Closure Tutorial – How Closures and Lexical Scope Work in JS</a><br></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo construir tu marca personal como nuevo desarrollador ]]>
                </title>
                <description>
                    <![CDATA[ Desde que comencé a publicar en Medium, he notado que mi blog [http://rickwest.co.uk/] y mis cuentas de redes sociales [http://twitter.com/rick_west8] han experimentado un aumento de tráfico. Un aumento muy leve, pero sigue siendo muy motivador y alentador. Esto me hizo pensar en algo que no se me había ocurrido hasta ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-construir-tu-marca-personal-como-nuevo-desarrollador/</link>
                <guid isPermaLink="false">608d5bb76bf0c60915255482</guid>
                
                    <category>
                        <![CDATA[ Carreras ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Tue, 29 Jun 2021 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/05/porsche.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Desde que comencé a publicar en Medium, he notado que mi <a href="http://rickwest.co.uk/">blog</a> y mis cuentas de <a href="http://twitter.com/rick_west8">redes sociales</a> han experimentado un aumento de tráfico. Un aumento muy leve, pero sigue siendo muy motivador y alentador.</p><p>Esto me hizo pensar en algo que no se me había ocurrido hasta hace poco. Algo que había estado descuidando. Mi marca personal.</p><p>Tengo un buen trabajo y no estoy buscando un trabajo nuevo. &nbsp;Pero había subestimado la importancia de tener una buena presencia online.</p><p>Mi ingenuidad se hizo más patente la semana pasada.</p><p>Mi empresa estaba reclutando para varios puestos y había recibido una gran cantidad de solicitudes. Para mi sorpresa, vi a mi jefe buscar en Google los nombres de los candidatos para evaluar su presencia online.</p><p>Mi jefe estaba usando esto como una forma de buscar contribuciones e información positiva. No estaba en Facebook tratando de averiguar qué hace el candidato un viernes por la noche. Estaba más interesado en:</p><ul><li>¿El candidato tenía un blog?</li><li>¿Intereses especiales?</li><li>¿Algún proyecto por el que se apasionara fuera del trabajo?</li></ul><p>Sin embargo, estoy seguro de que en otras empresas, esta podría ser diferente.</p><p>Me hizo pensar en mi propia “marca personal” y me inspiró a renovar un poco mi presencia online. Aquí van algunas cosas que hice, algunas observaciones que hice y algunos pasos sencillos que creo que tú también deberías seguir.</p><h3 id="inicia-y-mant-n-un-blog">Inicia y mantén un blog</h3><p>Si aún no lo tienes, intenta comprar tu nombre de dominio {tunombre} .com. Si no puedes obtener el .com, entonces el .co.uk u otro TLD (top-level-domain) local será suficiente.</p><p>Los nombres de dominio imaginativos son excelentes si estás tratando de construir un negocio. Pero, si estás construyendo una marca personal, entonces debería ser solo eso: personal.</p><p>Antes de que digas algo o dejes de leer, déjame decirte que los blogs están lejos de desaparecer.</p><p>No se trata de conseguir miles de visitantes en tu sitio web. Se trata de desarrollar una marca personal. Y, en última instancia, se trata de lo que sucede cuando un posible empleador o cliente escribe tu nombre en Google.</p><p>Tu blog no tiene por qué ser nada llamativo o caro. Un blog de WordPress con un tema gratuito será más que suficiente para comenzar. Hay otras plataformas que podrías usar como Jekyll. WordPress fue tan fácil de configurar y comenzar a usar que nunca sentí la necesidad de probar nada más.</p><p>No se trata de mostrar tus habilidades o proyectos de diseño. Se trata de que otros te puedan encontrar online y puedan contactar contigo.</p><p>No te preocupes demasiado por lo que debes escribir ni dediques horas y horas a jugar con tu blog. No debería quitarle tiempo a tu aprendizaje ni a tu tiempo en familia. Trata de publicar con regularidad y con coherencia.</p><p>Finalmente, intenta recordar que tus publicaciones no tienen por qué ser demasiado técnicas. Incluso si eres un principiante, siempre tendrás 1 día, 1 semana o 1 mes de experiencia más que cualquier otra persona. Alguien encontrará valor en lo que tienes que decir.</p><p>No tengas miedo de aprovechar la oportunidad para escribir sobre algo que no sea técnico. Escribe sobre un pasatiempo o interés. Utiliza tu blog como una forma de mostrar tu personalidad e intereses fuera del código. <strong>Intenta no ser demasiado conflictivo.</strong></p><h3 id="reg-strate-para-obtener-una-cuenta-de-twitter">Regístrate para obtener una cuenta de Twitter</h3><p>Yo no soy muy de redes sociales. Sin embargo, considerando mi marca personal, decidí registrarme para obtener una cuenta de Twitter.</p><p>Twitter es una manera fácil de obtener acceso directo a muchos miembros de "alto perfil" de la comunidad de programación. Por ejemplo, recientemente publiqué un tweet en el que expresaba mi interés en aprender el framework <a href="https://www.slimframework.com/">Slim</a>. Para mi sorpresa, la primera respuesta fue de uno de los principales contribuyentes al framework . ¿Quién mejor que él para obtener un consejo y una guía?</p><p>Además de ser parte de una comunidad, es una excelente manera de mantenerse al día con las noticias y los eventos de la industria. También es una excelente manera de romper el hielo y decir un "hola" virtual antes de toparse con alguien en una reunión o conferencia en persona.</p><p>Recuerda que tus tweets están ahí para que los vea todo el mundo. Entonces, con eso en mente, sé útil, amable, e intenta ofrecer algún valor. Los tweets inútiles sobre lo que cenaste y el dolor de espalda de la tía Madge harán que te dejen de seguir.</p><p>Las redes sociales son una gran oportunidad para construir tu marca personal, así que úsalas correctamente para establecer contactos y compartir tu entusiasmo y conocimiento.</p><h3 id="s-coherente-en-todas-las-plataformas">Sé coherente en todas las plataformas</h3><p>Cuando pienses en cualquier marca, sin duda la asociarás con un logo, eslogan o imagen en particular. Esto es exactamente lo mismo al evaluar tu marca personal.</p><p>Asegúrate de tener la misma foto de perfil y biografía en todas las plataformas. Cometí el error de tener una foto de perfil diferente en Medium a la que tenía en Twitter. La gente no los asoció de inmediato. Tu objetivo es que las personas te reconozcan a ti y a tu marca personal sin importar la plataforma.</p><h3 id="eres-un-desarrollador">ERES un desarrollador</h3><p>Incluso si todavía estás aprendiendo y eres nuevo(a) en el desarrollo, no obstaculices tus posibilidades de conseguir un trabajo. No pongas en tu blog y cuentas de redes sociales algo como "aspirante a desarrollador" o "desarrollador en formación".</p><p>¿Qué gerente de contratación va a estar interesado en un aspirante a desarrollador? Es una forma segura de ser eliminado en el primer corte.</p><p>Incluso si tienes un trabajo diario normal y has estado aprendiendo a codificar por las tardes, sigues siendo un "desarrollador" (¡que simplemente trabaja durante el día y escribe código por las tardes!).</p><p>Habrá muchas oportunidades para explicar tu nivel de experiencia en una fecha posterior. Pero las primeras impresiones cuentan, así que no te tropieces con el primer obstáculo.</p><p><strong>Eres </strong>un desarrollador y estás buscando trabajo como desarrollador, así que asegúrate de referirte a tí mismo como tal.</p><h3 id="-de-todos-modos-qu-quiere-decir-exactamente-junior">¿De todos modos, qué quiere decir exactamente Junior ?</h3><p>Me di cuenta de que en mi blog y en mis cuentas de redes sociales me refería a mí mismo como un desarrollador "junior". Tengo 30 años. ¡No hay nada de junior en eso!</p><p>En serio, junior no tiene sentido. Todo se reduce a la percepción de un individuo. Un desarrollador junior podría ser alguien con poca o ninguna experiencia laboral. Pero, ¿qué pasa si esa persona ha estado escribiendo código en su tiempo libre durante los últimos 10 años? ¿Son junior entonces? ¿O alguien podría tener algunos años de experiencia comercial pero aun así no ser muy bueno?</p><p>Si te refieres a ti mismo como un desarrollador junior, para. No te estás haciendo ningún favor. Estás limitando tu potencial de empleo. ¿Qué empresa o reclutador considerará un "junior" cuando esté anunciando un rol de desarrollador de nivel medio?</p><p>No querrás que digan: "Espera un momento. Cumples con todos los requisitos laborales y tienes varios años de experiencia. Pero lo siento, no estamos buscando un junior".</p><h3 id="si-tienes-una-especialidad-enfat-zala">Si tienes una especialidad, enfatízala</h3><p>En mi blog y en las redes sociales me refería a mí mismo como un "desarrollador web". Sí, desarrollo aplicaciones web utilizando tecnologías web. Más específicamente, soy un desarrollador de PHP.</p><p>Mis habilidades en JavaScript no son nada especiales, por lo que no estaré buscando un trabajo de desarrollador de JavaScript a corto plazo. Solo pasé aproximadamente una hora repasando un tutorial de Ruby on Rails, por lo que tampoco sería una opción. Así que decidí cambiar mi marca como desarrollador de PHP. Esto representa mi conjunto de habilidades y especialidad con mayor precisión.</p><p>Si quieres atraer a las oportunidades adecuadas, debes considerar exactamente lo que deseas mostrar.</p><h3 id="limpia-tu-cuenta-de-github">Limpia tu cuenta de Github</h3><p>Un colega y yo estábamos navegando en mi cuenta de Github la otra semana. Se sorprendió de lo activo que era fuera del trabajo ...</p><p>Hasta que se dio cuenta de que todo lo que tenía era una cuenta llena de proyectos "WIP" (work in progress - trabajo en curso) a medio terminar y desordenados. No era exactamente impresionante. Definitivamente no dio la impresión de que soy una persona que se entrega y que sabe cómo llevar un proyecto hasta el final.</p><p>Mi consejo: estar activo en GitHub es genial, pero si nunca vas a terminar esos proyectos, bórralos. Debes asegurarte de que cualquier gerente de contratación o reclutador vea los proyectos que has completado y de los que estás orgulloso, no aquellos en los que "tenías la intención de trabajar, pero no tenías tiempo para hacerlo".</p><h4 id="muestra-lo-que-te-apasiona">Muestra lo que te apasiona</h4><p>Usa tu blog, redes sociales, GitHub y presencia online para resaltar tu pasión por tu trabajo. Siempre que sea posible, muestra orgullo y entusiasmo por lo que haces.</p><p>Hablando del tema, te dejo con una de mis respuestas favoritas de stack-overflow. Elegir entre dos programadores: <a href="https://softwareengineering.stackexchange.com/questions/37339/choosing-between-two-programmers-experience-vs-passion">pasión vs experiencia</a>.</p><blockquote>Contrata al programador sin experiencia con pasión por el trabajo. Un programador apasionado aprenderá rápidamente, se preocupará por su trabajo y disfrutará haciéndolo. He trabajado con ambos tipos de programadores y siempre contrataría al apasionado antes que al experimentado.</blockquote><blockquote>La gente a la que no le gusta su trabajo acaba por generar problemas de calidad y de cumplimiento de los plazos.</blockquote><blockquote>Dado que declaras explícitamente que tienes los recursos para entrenar a alguien, esto es una obviedad. Contrata al programador apasionado.</blockquote><p>¡Gracias por leer! :) Si lo disfrutaste, presiona el botón del corazón ♡ a continuación. Hará que más personas vean esta historia aquí en Medium.</p><p>Siempre me alegra saber de personas de ideas afines, así que me puedes saludar en <a href="http://twitter.com/rick_west8">Twitter</a>. ¡Cuéntame cómo estás desarrollando tu propia marca personal!</p><p>Traducido del artículo de <a href="https://twitter.com/rick_west8">Rick West </a>- <a href="https://www.freecodecamp.org/news/building-your-personal-brand-as-a-new-web-developer-f6d4150fd217/">How to build your personal brand as a new developer</a> </p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo proteger un sitio web de WordPress existente en seis pasos sencillos ]]>
                </title>
                <description>
                    <![CDATA[ Si quieres construir un sitio web flexible hoy en día, es muy probable que utilices un sistema de gestión de contenido (CMS). Y WordPress es, con mucha diferencia, el más popular. En el último recuento, WordPress se usaba aproximadamente en el 40% de todos los sitios web en Internet [https://w3techs.com/technologies/overview/content_management]. ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-proteger-un-sitio-de-wordpress-existente-en-seis-sencillos-pasos/</link>
                <guid isPermaLink="false">607b05b9a48de608c011a891</guid>
                
                    <category>
                        <![CDATA[ WordPress ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Tue, 15 Jun 2021 07:20:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/06/wordpress-site-security-tips.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Si quieres construir un sitio web flexible hoy en día, es muy probable que utilices un sistema de gestión de contenido (CMS). Y WordPress es, con mucha diferencia, el más popular.</p><p>En el último recuento, WordPress se usaba aproximadamente<a href="https://w3techs.com/technologies/overview/content_management"> en el 40% de todos los sitios web en Internet</a>. Eso significa que si eres un programador web, es probable que te encuentres con WordPress en algún momento de tu carrera profesional.</p><p>Ya que WordPress se usa tanto, cualquier programador que trabaje con él debe tener mucho cuidado de protegerlo contra ataques externos. Y esos ataques continúan multiplicándose. En un solo incidente el año pasado, <a href="https://www.helpnetsecurity.com/2020/05/06/wordpress-extensive-attacks/">casi un millón de sitios web</a> fueron atacados en un solo mes.</p><p>El problema es que no hay dos sitios de WordPress creados de la misma forma, lo que significa que hay un número infinito de vulnerabilidades potenciales a las que hay que prestar atención. Y cuando añades plugins de terceras partes a la mezcla, se hace imposible montar una defensa de sitio web perfecta.</p><p>Pero hay algunas cosas que puedes hacer para fortalecer un sitio de WordPress contra ataques. &nbsp;Detendrán todas las amenazas excepto las más sofisticadas. Aquí van seis pasos de seguridad que debes seguir en cada sitio de WordPress con el que trabajes.</p><h2 id="paso-uno-actualizar-wordpress-a-la-ltima-versi-n"><strong>Paso Uno: Actualizar WordPress </strong>a la última versión</h2><p>Dado que WordPress es una pieza de software, es fundamental mantenerlo actualizado para corregir las vulnerabilidades a medida que se identifican. Pero un número sorprendentemente alto de desarrolladores y propietarios de sitios web se niegan a hacerlo.</p><p>Los datos recientes indican que hasta el 70% de las instalaciones conocidas de WordPress <a href="https://www.wpwhitesecurity.com/statistics-70-percent-wordpress-installations-vulnerable/">todavía usan versiones con vulnerabilidades conocidas</a>.</p><p>Aunque puede que creas que esta información haría sonar las alarmas en internet, el problema persiste. Parte de ello se debe a que las empresas no están dispuestas a pagar a profesionales para completar el trabajo. Y parte se debe a que ciertos sitios dependen de plugins heredados que no funcionarán con las versiones más recientes de WordPress.</p><p>Pero cualquier desarrollador que trabaje en un sitio web de este tipo está buscando problemas. Por lo tanto, sería mejor que insistieras en una actualización del sitio web cada vez que encuentres una instalación no actualizada de WordPress.</p><p>Si te tomas el tiempo de compartir algunas de las estadísticas de amenazas con el propietario del sitio web, en algún momento verá la luz. Asegúrate de hacer una copia de seguridad completa del sitio web &nbsp;antes de realizar cualquier cambio.</p><p>Si algo sale mal y las páginas se rompen o los plugins fallan, crearás un problema mayor del que resuelves. Según <a href="https://www.wsidigitalweb.co.uk/">WSI Digital Web</a>, este es un problema que se encuentran muchos desarrolladores y causa daños en el mundo real. Ellos han dicho,</p><blockquote>"Hemos tenido que hacer correcciones después de que actualizaciones fallidas de WordPress deshabilitaran páginas, debido a la rotura del sitio web. Cuando eso sucede, esas páginas pueden salirse de los índices de búsqueda muy pronto, por lo que es esencial revertir los cambios rápidamente".</blockquote><h2 id="paso-dos-eliminar-plugins-no-utilizados-y-actualizar-el-resto"><strong>Paso dos: &nbsp;</strong>Eliminar plugins no utilizados y actualizar el resto</h2><p>Igual que una instalación básica de WordPress, los plugins también sufren vulnerabilidades de vez en cuando, que los desarrolladores corrigen . Y WordPress depende mucho de plugins para proporcionar todo tipo de funcionalidades.</p><p>Por ejemplo, cuando recientemente trabajé en el sitio web de una <a href="https://www.yourchoiceplumbers.com.au/">empresa de fontanería</a> local, me sorprendió ver los plugins que usaban, dada la relativa simplicidad del sitio.</p><p>Pero la mejor manera de minimizar la superficie de ataque posible es, primero, &nbsp;eliminar cualquier plugin redundante o en desuso, y luego, buscar las actualizaciones disponibles. Eso simplificará las tareas de mantenimiento en curso y reducirá el potencial de vulnerabilidades.</p><p>Solamente una vez hecho esto, deberías verificar el estado de actualización de los plugins restantes.</p><p>Después de aplicar las actualizaciones disponibles, no supongas que todo está bien. Verifica si alguno de los plugins restantes no ha tenido actualizaciones en un tiempo e intenta averiguar por qué.</p><p>Si descubres que un desarrollador de plugins ha desaparecido o discontinuado un plugin, busca un reemplazo actual. Cuanto más tiempo pase un plugin sin ninguna actividad de desarrollo, mayores serán las probabilidades de que se convierta en un problema de seguridad.</p><h2 id="paso-tres-minimizar-los-permisos-de-usuario-y-los-inicios-de-sesi-n-de-seguridad"><strong>Paso tres: </strong>Minimizar los permisos de usuario y los inicios de sesión de seguridad</h2><p>Que el sitio de WordPress en el que estás trabajando no contenga vulnerabilidades conocidas, no significa que sea seguro. Esto se debe a que los <a href="https://www.malcare.com/blog/wordpress-brute-force/">ataques de fuerza bruta</a> a las credenciales son la forma más común en que los piratas informáticos obtienen acceso no autorizado a los sitios web de WordPress. Y la mejor manera de evitar daños es revisar los permisos de usuario y las políticas de contraseñas.</p><p>Primero, intenta reducir el número de cuentas que tienen acceso de nivel de administrador. &nbsp;No es raro que las pequeñas empresas designen a casi todos como administradores, pero ese es un riesgo enorme.</p><p>Por tanto, revisa cada cuenta y asigna el nivel de permiso más bajo posible de los grupos de acceso integrados:</p><ul><li><strong>Administradores Super</strong> – Los Superusuarios de WordPress. Intenta limitarlos a un máximo de dos.</li><li><strong>Administradores </strong>– Este es el permiso de usuario general más alto. Nuevamente, trata de mantenerlos al mínimo.</li><li><strong><strong>Editor</strong></strong> – Para usuarios que necesitan controlar y realizar cambios en todos los artículos publicados.</li><li><strong><strong>Autor </strong></strong>– Un usuario que solamente puede publicar y cambiar cosas bajo su nombre.</li><li><strong>Contribuidor<strong>– </strong></strong>Puede agregar, pero no publicar artículos bajo su nombre.</li><li><strong>Suscriptor<strong>– </strong></strong>No pueden realizar cambios en el sitio web, excepto en su perfil de usuario.</li></ul><p>Si encuentras usuarios que ya no necesitan acceso, elimínalos. Y luego, usa el complemento <a href="https://wordpress.org/plugins/google-authenticator/">Google Authenticator</a> u otro sistema de autentificación de dos factores para proteger las cuentas restantes.</p><h2 id="paso-cuatro-deshabilitar-la-ejecuci-n-de-php-en-carpetas-que-no-son-de-confianza"><strong>Paso cuatro: </strong>Deshabilitar la ejecución de PHP en carpetas que no son de confianza</h2><p>Hasta ahora, todos los pasos han girado en torno a la prevención de ataques comunes de bajo nivel.</p><p>Pero hay algunas amenazas más sofisticadas para los sitios de WordPress de las que también deberías preocuparte. Y muchas de ellas involucran a atacantes que encuentran formas de ejecutar código en un sitio sin obtener acceso a la cuenta en absoluto.</p><p>Esto es común en WordPress debido a la forma en la que administra los permisos de carpeta predeterminados.</p><p>Por ejemplo, si instalas un plugin para administrar los medios cargados por el usuario, como imágenes y videos, necesitarás una carpeta de carga que se pueda acceder desde el exterior. Si un atacante puede obtener acceso a esa carpeta, puede intentar cargar un script malicioso y usarlo para alterar o apoderarse de todo el sitio web.</p><p>La buena noticia es que puedes protegerte contra eso con un simple archivo de control de acceso en las carpetas necesarias.</p><p>Lo que tendrás que hacer es crear un nuevo archivo en cada carpeta de escritura llamado .htaccess. Es un archivo de texto que le dice al servidor web qué permitir o no permitir en un directorio determinado. En él, incluye lo siguiente:</p><pre><code class="language-php"># BEGIN WordPress
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteBase
RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L] &lt;/IfModule&gt;
# END WordPress
&lt;FilesMatch "\.(php|php\.)$"&gt;
Order Allow,Deny
Deny from all
&lt;/FilesMatch&gt;</code></pre><p>Este archivo .htaccess permitirá a los usuarios cargar los tipos de archivos que desee, pero evitará que alguien cargue un código ejecutable en el directorio de escritura.</p><p>Puedes hacer esto en cualquier carpeta de usuario que desees proteger. Pero ten cuidado de no abusar de estas restricciones. La mayor parte de WordPress implica la ejecución de PHP, y puedes deshabilitar todo tu sitio web si colocas uno de estos &nbsp;archivos en el lugar equivocado.</p><h2 id="paso-cinco-deshabilitar-la-visualizaci-n-de-errores-de-php"><strong>Paso cinco: </strong>Deshabilitar la visualización de errores de PHP</h2><p>Obtener acceso de escritura y ejecución a directorios es solo una de las formas en que un atacante puede intentar ejecutar código malicioso en un sitio web de WordPress. También pueden buscar partes del sitio que ejecuten PHP (que está prácticamente en todas partes donde no lo has bloqueado) y encontrar puntos débiles allí. Pero puedes hacer su trabajo mucho más difícil.</p><p>Para hacer eso, debes desactivar la visualización de errores de PHP para que no puedan ver ningún resultado cuando intenten romper las páginas del sitio a propósito. Si el sitio les da pistas sobre qué funciona y qué no, podría proporcionar una hoja de ruta para encontrar una manera de explotar las páginas del sitio existentes.</p><p>La buena noticia es que es sencillo desactivar los informes de errores de PHP en WordPress. Todo lo que tienes que hacer es editar el archivo wp-config.php del sitio web, que se encuentra en el directorio raíz, y contiene la información de configuración básica del sitio.</p><p>Simplemente agrega la siguiente línea al archivo:</p><pre><code class="language-php">define( 'WP_DEBUG', false);</code></pre><p>Esto deshabilitará la depuración de PHP en todo el sitio web. Toma nota cuando realices este cambio en caso de que el sitio web tenga problemas en el futuro y requiera esfuerzos de depuración autorizados.</p><h2 id="paso-seis-deshabilitar-la-edici-n-de-temas-y-plugins"><strong>Paso seis – </strong>Deshabilitar la edición de temas y plugins</h2><p>Incluso después de haber hecho todo lo anterior, no puedes estar seguro de que nadie llegará a un sitio de WordPress con la intención de dañar. Por lo tanto, debes poner en el camino un conjunto final de obstáculos.</p><p>Esto no evitará que algún atacante serio cause estragos, pero podría darles a los operadores del sitio web tiempo suficiente para darse cuenta de que algo anda mal y tomar medidas para corregirlo.</p><p>Lo que debes hacer es deshabilitar el tema de WordPress incorporado y la capacidad de edición de plugins para dificultar que alguien que haya obtenido acceso a la interfaz administrativa altere la codificación base del sitio.</p><p>Una vez más, puedes hacer esto modificando el archivo wp-config.php del sitio web, ubicado en su directorio raíz. Agrega la siguiente línea justo antes de donde veas las palabras 'That's all, stop editing! Happy publishing':</p><pre><code class="language-php">define( 'DISALLOW_FILE_EDIT', true );</code></pre><p>Esto ocultará los editores de temas y plugins de la interfaz administrativa y evitará cualquier medio fácil de alterar los archivos del sitio web. Para deshacer este cambio, el atacante necesitaría acceso FTP o de nivel de archivo al servidor web, lo que al menos lo ralentizará un poco.</p><p>Y como nota final, aunque en otros lugares puedes ver consejos que te indiquen que uses un plugin de fragmento de código para realizar estos cambios, no lo hagas. Si lo haces, un atacante podría usar ese mismo plugin para deshacer tus cambios, anulando el valor de seguridad de realizar los cambios en primer lugar.</p><h2 id="las-protecciones-imperfectas-tambi-n-vale-la-pena-probarlas"><strong>Las </strong>protecciones imperfectas también vale la pena probarlas </h2><p>La conclusión es que WordPress siempre será una especie de víctima de su propio éxito. Hay muchos sitios web que confían en él, lo que lo convierte en un objetivo grande y atractivo para los atacantes.</p><p>Y aunque estas seis medidas no detendrán todos los tipos de amenazas posibles, harán un trabajo decente defendiéndose contra la mayoría de los ataques de menor nivel.</p><p>También puedes (y debes) intentar proteger las bases de datos de tu sitio web cambiando el prefijo predeterminado de las tablas a algo confuso. Pero como eso está un poco fuera del alcance de un sitio web existente, lo he omitido aquí como medida de seguridad.</p><p>Si quieres intentarlo, aquí encontrarás <a href="https://www.wpbeginner.com/wp-tutorials/how-to-change-the-wordpress-database-prefix-to-improve-security/">un excelente tutorial</a>. De lo contrario, estate satisfecho de haber hecho tu parte para ayudar a mantener un poco más seguro uno de los innumerables sitios de WordPress en funcionamiento en todo el mundo.</p><p>Traducción del artículo de <strong><a href="https://www.freecodecamp.org/news/author/andrej/"><strong>Andrej Kovacevic</strong></a> - </strong><a href="https://www.freecodecamp.org/news/secure-wordpress-site-six-steps/"><strong>How to Secure an Existing WordPress Site in Six Easy Steps</strong></a></p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ ¿Qué es Glassmorphism? Crea este nuevo efecto de diseño utilizando solamente HTML y CSS ]]>
                </title>
                <description>
                    <![CDATA[ El Glassmorphism es una nueva tendencia muy popular en la actualidad. La verás mucho en sitios web como Dribbble, e incluso compañías grandes como Apple y Microsoft la usan. Deja que te muestre esta nueva tendencia del glassmorphism. Después de la tendencia neumorphism [https://demo.themesberg.com/neumorphism-ui/] del año pasado, que tenía un ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/que-es-glassmorphism-crea-este-nuevo-efecto-de-diseno-utilizando-solamente-html-y-css/</link>
                <guid isPermaLink="false">6069d408669b0108f64b7210</guid>
                
                    <category>
                        <![CDATA[ Diseño ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ GM Fuster ]]>
                </dc:creator>
                <pubDate>Tue, 01 Jun 2021 13:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/05/freecodecamp-glass-1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>El Glassmorphism es una nueva tendencia muy popular en la actualidad. La verás mucho en sitios web como Dribbble, e incluso compañías grandes como Apple y Microsoft la usan.</p><p>Deja que te muestre esta nueva tendencia del <strong><strong>glassmorphism</strong></strong>. Después de la tendencia <a href="https://demo.themesberg.com/neumorphism-ui/">neumorphism</a> del año pasado, que tenía un estilo controvertido con poca accesibilidad, esta tendencia parece mucho más prometedora.</p><h2 id="-qu-es-glassmorphism"><strong>¿</strong>Qué<strong> es glassmorphism?</strong></h2><p>Básicamente, el concepto principal de esta tendencia es un fondo semitransparente, con una sombra y borde sublimes.</p><p>Pero también se añade un difuminado al fondo para que lo que queda detrás del fondo se “transforme” elegantemente dentro del mismo elemento. &nbsp;¿Tiene sentido?</p><p>Aquí va un ejemplo:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2021/03/glassmorphism-ui.png" class="kg-image" alt="Glassmorphism" width="600" height="400" loading="lazy"></figure><p>Este es un ejemplo real de glassmorphism en acción, que también puedes ver en el sitio web <a href="https://ui.glass/">ui.glass</a> (es una librería futura de CSS UI).</p><p>El efecto difuminado que he mencionado antes es lo que se ve detrás del código a la derecha de la imagen superior. &nbsp;¿Ves cómo se transforma en fondo pero al mismo tiempo se mantiene legible y agradable a la vista?</p><p>Ese es el efecto que quiero enseñarte a crear en este tutorial. Veremos como aplicarlo usando solamente HTML y CSS.</p><h2 id="primeros-pasos">Primeros pasos</h2><p>Todo lo que necesitas para este tutorial es un navegador y un editor de código, porque solamente vamos a usar HTML y CSS.</p><p>El elemento final que vamos a construir será como esto:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-24-at-17.35.18.png" class="kg-image" alt="Screenshot-2021-03-24-at-17.35.18" width="600" height="400" loading="lazy"><figcaption>Ejemplo de Glassmorphism</figcaption></figure><p>Primero lo primero, vamos a crear un fichero básico de HTML con el siguiente código:</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta http-equiv="X-UA-Compatible" content="IE=edge"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
  &lt;title&gt;Glassmorphism Effect&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- el código va aquí    --&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><p>No me gusta mucho la fuente de letra por defecto, así que vamos a usar algo más bonito de Google Fonts. &nbsp;Me gusta mucho la fuente Inter, así que vamos a incluirla en nuestro proyecto dentro de la etiqueta <code>head</code> :</p><figure class="kg-card kg-code-card"><pre><code class="language-html">&lt;link rel="preconnect" href="https://fonts.gstatic.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&amp;display=swap" rel="stylesheet"&gt;</code></pre><figcaption>Google Fonts</figcaption></figure><p>Ahora, vamos a añadir algunos estilos básicos a nuestra etiqueta <code>body</code> y también vamos a crear un fondo usando colores vivos y gradientes:</p><pre><code class="language-css">body {
  padding: 4.5rem;
  margin: 0;
  background: #edc0bf;
  background: linear-gradient(90deg, #edc0bf 0,#c4caef 58%);
  font-family: 'Inter', sans-serif;
}</code></pre><p>¡Perfecto! Ahora que tenemos el código y estilos básicos, vamos a crear un elemento tarjeta (card) dentro de la etiqueta <code>body</code> :</p><pre><code class="language-html">&lt;div class="card"&gt;
    &lt;h3 class="card-title"&gt;Glassmorphism is awesome&lt;/h3&gt;
    &lt;p&gt;A modern CSS UI library based on the glassmorphism design principles that will help you quickly design and build beautiful websites and applications.&lt;/p&gt;
    &lt;a href="https://ui.glass"&gt;Read more&lt;/a&gt;
&lt;/div&gt;</code></pre><p>El contenido dentro de la tarjeta (card) no importa – Puedes añadir botones extra, iconos, y otros elementos.</p><p>Antes de aplicar el efecto <strong><strong>glassmorphism</strong></strong> a la tarjeta, vamos a aplicar algunos espacios y estilos a la tipografía añadiendo el siguiente CSS:</p><pre><code class="language-css">.card {
  width: 400px;
  height: auto;
  padding: 2rem;
  border-radius: 1rem;
}

.card-title {
  margin-top: 0;
  margin-bottom: .5rem;
  font-size: 1.2rem;
}

p, a {
  font-size: 1rem;
}

a {
  color: #4d4ae8;
  text-decoration: none;
}</code></pre><p>¡Excelente trabajo! Lo siguiente es enseñarte como aplicar el efecto especial.</p><h2 id="como-aplicar-el-efecto-glassmorphism-usando-css">Como aplicar el efecto<strong> glassmorphism usando CSS</strong></h2><p>Todo lo que necesitas hacer es aplicar un color de fondo semitransparente y aplicar un difuminado usando la propiedad <code>backdrop-filter</code> . Añade los siguientes estilos al elemento <code>.card</code> usando CSS:</p><figure class="kg-card kg-code-card"><pre><code class="language-css">.card {
	/* other styles */
	background: rgba(255, 255, 255, .7);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
}</code></pre><figcaption>Glassmorphism using CSS</figcaption></figure><p>Ahora ya hemos aplicado con éxito el estilo glassmorphism a la tarjeta (card) – ¿Pero dónde está el efecto?</p><p>Todavía necesitamos algo detrás de la tarjeta, como una forma o una imagen, para poder verlo en acción.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-24-at-12.57.00.png" class="kg-image" alt="Screenshot-2021-03-24-at-12.57.00" width="600" height="400" loading="lazy"><figcaption>Ejemplo sin la forma</figcaption></figure><p>Añadamos una forma utilizando un elemento <code>img</code> &nbsp;justo detrás del comienzo de la etiqueta <code>body</code> :</p><pre><code class="language-html">&lt;img class="shape" src="https://s3.us-east-2.amazonaws.com/ui.glass/shape.svg" alt=""&gt;</code></pre><p>Y apliquemos el siguiente estilo CSS al elemento <code>.shape</code> para posicionarlo en la página correctamente:</p><pre><code class="language-css">.shape {
  position: absolute;
  width: 150px;
  top: .5rem;
  left: .5rem;
}</code></pre><p>Ahora deberías ver el efecto completo de la nueva tendencia de diseño glassmorphism. &nbsp;¡Enhorabuena!</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot-2021-03-24-at-17.35.18.png" class="kg-image" alt="Screenshot-2021-03-24-at-17.35.18" width="600" height="400" loading="lazy"><figcaption>Ejemplo de Glassmorphism</figcaption></figure><p>Puedes ver esto en <a href="https://codepen.io/themesberg/pen/RwKNMeY">codepen</a> para tomar el código y estilos de esta guía directamente.</p><h2 id="compatibilidad-con-navegadores">Compatibilidad con navegadores</h2><p>Una de las mayores desventajas del glassmorphism es que la propiedad <code>backdrop-filter</code> no es compatible con Internet Explorer 11, y por defecto está desactivada en Firefox.</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2021/03/glassmorphism-browser-support.png" class="kg-image" alt="glassmorphism-browser-support" width="600" height="400" loading="lazy"><figcaption>Browser support for backdrop-filter</figcaption></figure><p>De todos modos, de acuerdo al sitio web <a href="https://caniuse.com/css-backdrop-filter">caniuse.com</a> , más del 88.2% de los navegadores en el mundo son compatibles con este estilo. Si Firefox decide activar esta propiedad por defecto, y a medida que el uso de navegadores más antiguos (como IE 11) disminuya, creo que en los próximos años glassmorphism &nbsp;será utilizado a una escala mucho mayor .</p><p>Hasta entonces, puedes usarlo en tus proyectos personales, o simplemente pasarlo bien creando páginas con esta estupenda tendencia de diseño.</p><h2 id="conclusi-n">Conclusión</h2><p>Espero que este tutorial te haya ayudado a aprender más sobre esta nueva tendencia.</p><p>Si quieres explorar más, me gustaría mostrarte un proyecto en el que he estado trabajando con un amigo.</p><p>Se llama <a href="https://ui.glass/">Glassmorphism UI</a>, y será una librería CSS UI gratis y open source basada en esta nueva tendencia. Apúntate con tu correo electrónico para recibir actualizaciones sobre su progreso y ser uno de los primeros en saber cuando se lanza.</p><p>La librería estará disponible vía NPM, pero también en GitHub con licencia MIT.</p><p>Traducido del artículo de <a href="https://www.freecodecamp.org/news/author/zoltan/"><strong>Zoltán Szőgyényi</strong></a><strong> - <a href="https://www.freecodecamp.org/news/glassmorphism-design-effect-with-html-css/">What is Glassmorphism? Create This New Design Effect Using Only HTML and CSS</a></strong></p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
