Revert "docs: translate tutorial/toh-pt3.md (#279)"

This reverts commit cbe53247facab11ceddca3cb1a74fe33a818c0ed.
This commit is contained in:
Antonio Cardenas 2020-10-22 14:15:01 -06:00 committed by GitHub
parent 3da8ebf27e
commit 138dd66707
2 changed files with 80 additions and 241 deletions

View File

@ -1,173 +0,0 @@
# Create a feature component
At the moment, the `HeroesComponent` displays both the list of heroes and the selected hero's details.
Keeping all features in one component as the application grows will not be maintainable.
You'll want to split up large components into smaller sub-components, each focused on a specific task or workflow.
In this page, you'll take the first step in that direction by moving the hero details into a separate, reusable `HeroDetailComponent`.
The `HeroesComponent` will only present the list of heroes.
The `HeroDetailComponent` will present details of a selected hero.
<div class="alert is-helpful">
For the sample app that this page describes, see the <live-example></live-example>.
</div>
## Make the `HeroDetailComponent`
Use the Angular CLI to generate a new component named `hero-detail`.
<code-example language="sh" class="code-shell">
ng generate component hero-detail
</code-example>
The command scaffolds the following:
* Creates a directory `src/app/hero-detail`.
Inside that directory four files are generated:
* A CSS file for the component styles.
* An HTML file for the component template.
* A TypeScript file with a component class named `HeroDetailComponent`.
* A test file for the `HeroDetailComponent` class.
The command also adds the `HeroDetailComponent` as a declaration in the `@NgModule` decorator of the `src/app/app.module.ts` file.
### Write the template
Cut the HTML for the hero detail from the bottom of the `HeroesComponent` template and paste it over the generated boilerplate in the `HeroDetailComponent` template.
The pasted HTML refers to a `selectedHero`.
The new `HeroDetailComponent` can present _any_ hero, not just a selected hero.
So replace "selectedHero" with "hero" everywhere in the template.
When you're done, the `HeroDetailComponent` template should look like this:
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.html" header="src/app/hero-detail/hero-detail.component.html"></code-example>
### Add the `@Input()` hero property
The `HeroDetailComponent` template binds to the component's `hero` property
which is of type `Hero`.
Open the `HeroDetailComponent` class file and import the `Hero` symbol.
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts"
region="import-hero" header="src/app/hero-detail/hero-detail.component.ts (import Hero)">
</code-example>
The `hero` property
[must be an _Input_ property](guide/inputs-outputs "Input and Output properties"),
annotated with the `@Input()` decorator,
because the _external_ `HeroesComponent` [will bind to it](#heroes-component-template) like this.
<code-example path="toh-pt3/src/app/heroes/heroes.component.html" region="hero-detail-binding">
</code-example>
Amend the `@angular/core` import statement to include the `Input` symbol.
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts" region="import-input" header="src/app/hero-detail/hero-detail.component.ts (import Input)"></code-example>
Add a `hero` property, preceded by the `@Input()` decorator.
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts" header="src/app/hero-detail/hero-detail.component.ts" region="input-hero"></code-example>
That's the only change you should make to the `HeroDetailComponent` class.
There are no more properties. There's no presentation logic.
This component simply receives a hero object through its `hero` property and displays it.
## Show the `HeroDetailComponent`
The `HeroesComponent` is still a master/detail view.
It used to display the hero details on its own, before you cut that portion of the template. Now it will delegate to the `HeroDetailComponent`.
The two components will have a parent/child relationship.
The parent `HeroesComponent` will control the child `HeroDetailComponent`
by sending it a new hero to display whenever
the user selects a hero from the list.
You won't change the `HeroesComponent` _class_ but you will change its _template_.
{@a heroes-component-template}
### Update the `HeroesComponent` template
The `HeroDetailComponent` selector is `'app-hero-detail'`.
Add an `<app-hero-detail>` element near the bottom of the `HeroesComponent` template, where the hero detail view used to be.
Bind the `HeroesComponent.selectedHero` to the element's `hero` property like this.
<code-example path="toh-pt3/src/app/heroes/heroes.component.html" region="hero-detail-binding" header="heroes.component.html (HeroDetail binding)">
</code-example>
`[hero]="selectedHero"` is an Angular [property binding](guide/property-binding).
It's a _one way_ data binding from
the `selectedHero` property of the `HeroesComponent` to the `hero` property of the target element, which maps to the `hero` property of the `HeroDetailComponent`.
Now when the user clicks a hero in the list, the `selectedHero` changes.
When the `selectedHero` changes, the _property binding_ updates `hero`
and the `HeroDetailComponent` displays the new hero.
The revised `HeroesComponent` template should look like this:
<code-example path="toh-pt3/src/app/heroes/heroes.component.html"
header="heroes.component.html"></code-example>
The browser refreshes and the app starts working again as it did before.
## What changed?
As [before](tutorial/toh-pt2), whenever a user clicks on a hero name,
the hero detail appears below the hero list.
Now the `HeroDetailComponent` is presenting those details instead of the `HeroesComponent`.
Refactoring the original `HeroesComponent` into two components yields benefits, both now and in the future:
1. You simplified the `HeroesComponent` by reducing its responsibilities.
1. You can evolve the `HeroDetailComponent` into a rich hero editor
without touching the parent `HeroesComponent`.
1. You can evolve the `HeroesComponent` without touching the hero detail view.
1. You can re-use the `HeroDetailComponent` in the template of some future component.
## Final code review
Here are the code files discussed on this page.
<code-tabs>
<code-pane header="src/app/hero-detail/hero-detail.component.ts" path="toh-pt3/src/app/hero-detail/hero-detail.component.ts">
</code-pane>
<code-pane header="src/app/hero-detail/hero-detail.component.html" path="toh-pt3/src/app/hero-detail/hero-detail.component.html">
</code-pane>
<code-pane header="src/app/heroes/heroes.component.html" path="toh-pt3/src/app/heroes/heroes.component.html">
</code-pane>
<code-pane header="src/app/app.module.ts" path="toh-pt3/src/app/app.module.ts">
</code-pane>
</code-tabs>
## Summary
* You created a separate, reusable `HeroDetailComponent`.
* You used a [property binding](guide/property-binding) to give the parent `HeroesComponent` control over the child `HeroDetailComponent`.
* You used the [`@Input` decorator](guide/inputs-outputs)
to make the `hero` property available for binding
by the external `HeroesComponent`.

View File

@ -1,140 +1,148 @@
# Crear un componente de características # Create a feature component
Por el momento, el `HeroesComponent` muestra tanto la lista de héroes como los detalles de los héroes seleccionados. At the moment, the `HeroesComponent` displays both the list of heroes and the selected hero's details.
Mantener toda la funcionalidad en un componente se vuelve menos sostenible a medida que la aplicación crece. Keeping all features in one component as the application grows will not be maintainable.
Deberá dividir un componente grande en subcomponentes más pequeños que se centren en una tarea o flujo de trabajo en particular. You'll want to split up large components into smaller sub-components, each focused on a specific task or workflow.
Esta página da el primer paso en ese camino moviendo los detalles del héroe a otro `HeroDetailComponent` reutilizable. In this page, you'll take the first step in that direction by moving the hero details into a separate, reusable `HeroDetailComponent`.
`HeroesComponent` solo muestra una lista de héroes. The `HeroesComponent` will only present the list of heroes.
`HeroDetailComponent` muestra los detalles del héroe seleccionado. The `HeroDetailComponent` will present details of a selected hero.
<div class="alert is-helpful"> <div class="alert is-helpful">
Para ver la aplicación de ejemplo que describe esta página, consulte el <live-example></live-example>.
For the sample app that this page describes, see the <live-example></live-example>.
</div> </div>
## Crear `HeroDetailComponent` ## Make the `HeroDetailComponent`
Usa el CLI de Angular para generar un nuevo componente llamado `hero-detail`. Use the Angular CLI to generate a new component named `hero-detail`.
<code-example language="sh" class="code-shell"> <code-example language="sh" class="code-shell">
ng generate component hero-detail ng generate component hero-detail
</code-example> </code-example>
Este comando generará una plantilla para el archivo `HeroDetailComponent` y declarará este componente en el `AppModule`. The command scaffolds the following:
Este comando produce la siguiente plantilla:
* Crear el directorio `src/app/hero-detail` * Creates a directory `src/app/hero-detail`.
Genera cuatro archivos en este directorio: Inside that directory four files are generated:
* Archivo CSS para estilo de componente * A CSS file for the component styles.
* Archivo HTML para la plantilla el componente * An HTML file for the component template.
* Archivo TypeScript de la clase de componente denominada `HeroDetailComponent` * A TypeScript file with a component class named `HeroDetailComponent`.
* Archivo de prueba de la clase `HeroDetailComponent` * A test file for the `HeroDetailComponent` class.
Este comando también agrega `HeroDetailComponent` como `declaraciones` en el decorador `@ NgModule` del archivo `src/app/app.module.ts`. The command also adds the `HeroDetailComponent` as a declaration in the `@NgModule` decorator of the `src/app/app.module.ts` file.
### Escribir plantilla
Corta el HTML de detalles del héroe desde la parte inferior de la plantilla `HeroesComponent` y pégalo en la plantilla generada en las plantilla `HeroDetailComponent`. ### Write the template
Las referencias HTML pegadas `selectedHero`. Cut the HTML for the hero detail from the bottom of the `HeroesComponent` template and paste it over the generated boilerplate in the `HeroDetailComponent` template.
El nuevo `HeroDetailComponent` puede mostrar _cualquier_héroe, no solo el héroe seleccionado.
Por lo tanto, reemplaza todos los "selectedHero" en la plantilla con "hero".
Cuando termines, las plantilla `HeroDetailComponent` deberían verse así: The pasted HTML refers to a `selectedHero`.
The new `HeroDetailComponent` can present _any_ hero, not just a selected hero.
So replace "selectedHero" with "hero" everywhere in the template.
When you're done, the `HeroDetailComponent` template should look like this:
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.html" header="src/app/hero-detail/hero-detail.component.html"></code-example> <code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.html" header="src/app/hero-detail/hero-detail.component.html"></code-example>
### Añadir la propiedad `@Input()` al héroe ### Add the `@Input()` hero property
Las plantillas `HeroDetailComponent` están vinculadas a la propiedad `hero` de un componente que es del tipo `Hero`. The `HeroDetailComponent` template binds to the component's `hero` property
which is of type `Hero`.
Abre el archivo de clase `HeroDetailComponent` e importe el símbolo `Hero`. Open the `HeroDetailComponent` class file and import the `Hero` symbol.
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts" <code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts"
region="import-hero" header="src/app/hero-detail/hero-detail.component.ts (import Hero)"> region="import-hero" header="src/app/hero-detail/hero-detail.component.ts (import Hero)">
</code-example> </code-example>
La propiedad `hero` debe ser una [_propiedad de entrada_](guide/template-syntax#inputs-outputs " Input and Output properties"), anotada con el decorador `@Input()` porque el `HeroesComponent` _externo_ [se vinculará de esta manera.](#heroes-component-template) The `hero` property
[must be an _Input_ property](guide/inputs-outputs "Input and Output properties"),
annotated with the `@Input()` decorator,
because the _external_ `HeroesComponent` [will bind to it](#heroes-component-template) like this.
<code-example path="toh-pt3/src/app/heroes/heroes.component.html" region="hero-detail-binding"> <code-example path="toh-pt3/src/app/heroes/heroes.component.html" region="hero-detail-binding">
</code-example> </code-example>
Modifique la declaración de importación `@angular/core` para incluir el símbolo `Input`. Amend the `@angular/core` import statement to include the `Input` symbol.
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts" region="import-input" header="src/app/hero-detail/hero-detail.component.ts (import Input)"></code-example> <code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts" region="import-input" header="src/app/hero-detail/hero-detail.component.ts (import Input)"></code-example>
Agrega la propiedad `hero` antepuesta por el decorador `@Input()`. Add a `hero` property, preceded by the `@Input()` decorator.
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts" header="src/app/hero-detail/hero-detail.component.ts" region="input-hero"></code-example> <code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts" header="src/app/hero-detail/hero-detail.component.ts" region="input-hero"></code-example>
Este es el único cambio que debe realizar en la clase `HeroDetailComponent`. That's the only change you should make to the `HeroDetailComponent` class.
No se requieren más propiedades o lógica de visualización. There are no more properties. There's no presentation logic.
Este componente solo toma un objeto héroe a través de la propiedad `hero` y lo muestra. This component simply receives a hero object through its `hero` property and displays it.
## Mostrar `HeroDetailComponent` ## Show the `HeroDetailComponent`
El `HeroesComponent` todavía está en la vista maestra/detalle. The `HeroesComponent` is still a master/detail view.
Hasta que eliminé los detalles del héroe de Plantillas, lo estaba mostrando en este componente. Ahora deleguemos a `HeroDetailComponent`. It used to display the hero details on its own, before you cut that portion of the template. Now it will delegate to the `HeroDetailComponent`.
Los dos componentes tienen una relación padre-hijo. The two components will have a parent/child relationship.
Para mostrar un nuevo héroe cada vez que el usuario selecciona un héroe de la lista, The parent `HeroesComponent` will control the child `HeroDetailComponent`
El padre `HeroesComponent` controla al hijo `HeroDetailComponent` enviándolo. by sending it a new hero to display whenever
the user selects a hero from the list.
No cambiarás la _clase_ de `HeroesComponent` pero cambiarás su _template_. You won't change the `HeroesComponent` _class_ but you will change its _template_.
{@a heroes-component-template} {@a heroes-component-template}
### Actualizar las plantillas `HeroesComponent` ### Update the `HeroesComponent` template
El selector para `HeroDetailComponent` es `'app-hero-detail'`. The `HeroDetailComponent` selector is `'app-hero-detail'`.
Add an `<app-hero-detail>` element near the bottom of the `HeroesComponent` template, where the hero detail view used to be.
Agrega un elemento `<app-hero-detail>` a la parte inferior de las plantillas `HeroesComponent` donde la vista detallada de héroe existió una vez. Bind the `HeroesComponent.selectedHero` to the element's `hero` property like this.
Vincula `HeroesComponent.selectedHero` a la propiedad `hero` de este elemento de la siguiente manera:
<code-example path="toh-pt3/src/app/heroes/heroes.component.html" region="hero-detail-binding" header="heroes.component.html (HeroDetail binding)"> <code-example path="toh-pt3/src/app/heroes/heroes.component.html" region="hero-detail-binding" header="heroes.component.html (HeroDetail binding)">
</code-example> </code-example>
`[hero]="selectedHero"` es el [enlace de propiedad](guide/template-syntax#property-binding). de Angular `[hero]="selectedHero"` is an Angular [property binding](guide/property-binding).
Este es un enlace de datos unidireccional de la propiedad `selectedHero` `HeroesComponent` a la propiedad `hero` del elemento objetivo. It's a _one way_ data binding from
Aquí se asigna la propiedad `hero` de `HeroDetailComponent`. the `selectedHero` property of the `HeroesComponent` to the `hero` property of the target element, which maps to the `hero` property of the `HeroDetailComponent`.
Cuando el usuario hace clic en un héroe en la lista, el `selectedHero` cambia. Now when the user clicks a hero in the list, the `selectedHero` changes.
Cuando `selectedHero` cambia,el _enlace de propiedad_ actualiza `hero` y When the `selectedHero` changes, the _property binding_ updates `hero`
`HeroDetailComponent` muestra el nuevo héroe. and the `HeroDetailComponent` displays the new hero.
La plantilla modificada de `HeroesComponent` se ve así: The revised `HeroesComponent` template should look like this:
<code-example path="toh-pt3/src/app/heroes/heroes.component.html" <code-example path="toh-pt3/src/app/heroes/heroes.component.html"
header="heroes.component.html"></code-example> header="heroes.component.html"></code-example>
Una vez que se actualiza el navegador, la aplicación comenzará a funcionar nuevamente como antes. The browser refreshes and the app starts working again as it did before.
## ¿Que ha cambiado? ## What changed?
[Como antes](tutorial/toh-pt2), cada vez que un usuario hace clic en el nombre de un héroe, el detalle del héroe aparece debajo de la lista de héroes. Ahora HeroDetailComponent presenta esos detalles en lugar de HeroesComponent. As [before](tutorial/toh-pt2), whenever a user clicks on a hero name,
the hero detail appears below the hero list.
Now the `HeroDetailComponent` is presenting those details instead of the `HeroesComponent`.
Refactorizar el `HeroesComponent` original en dos componentes te beneficiará ahora y en el futuro. Refactoring the original `HeroesComponent` into two components yields benefits, both now and in the future:
1. Simplificado `HeroesComponent` al reducir su responsabilidad. 1. You simplified the `HeroesComponent` by reducing its responsibilities.
1. Puedes convertir un `HeroDetailComponent` en un editor enriquecido de héroes sin tocar el padre `HeroesComponent` principal. 1. You can evolve the `HeroDetailComponent` into a rich hero editor
without touching the parent `HeroesComponent`.
1. Puedes evolucionar `HeroesComponent` sin tocar la vista de detalles del héroe. 1. You can evolve the `HeroesComponent` without touching the hero detail view.
1. Puedes reutilizar `HeroDetailComponent` en futuros componentes de Plantillas. 1. You can re-use the `HeroDetailComponent` in the template of some future component.
## Revisión final del código ## Final code review
Los archivos de código descritos en esta página son: Here are the code files discussed on this page.
<code-tabs> <code-tabs>
@ -152,10 +160,14 @@ Los archivos de código descritos en esta página son:
</code-tabs> </code-tabs>
## Resumen ## Summary
* Creaste un `HeroDetailComponent` independiente y reutilizable. * You created a separate, reusable `HeroDetailComponent`.
* Usaste el [enlace de propiedad](guide/template-syntax#property-binding) para que el padre `HeroesComponent` pueda controlar al hijo `HeroDetailComponent`.
* Usaste el [`decorador @Input`](guide/template-syntax#inputs-outputs) para hacer que la propiedad del heroe esté disponible para ser vinculada por el componente `HeroesComponent` externamente. * You used a [property binding](guide/property-binding) to give the parent `HeroesComponent` control over the child `HeroDetailComponent`.
* You used the [`@Input` decorator](guide/inputs-outputs)
to make the `hero` property available for binding
by the external `HeroesComponent`.