Skip to content

Commit

Permalink
Versión sin subcomponentes
Browse files Browse the repository at this point in the history
  • Loading branch information
sigdeletras committed May 13, 2020
1 parent 617e281 commit cfafa21
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 140 deletions.
81 changes: 22 additions & 59 deletions geoapp/src/components/TableList/TableList.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,5 @@
import React, { Component } from "react";
import PubSub from "pubsub-js";
// import './TableList.css';

const TableHeader = (props) => {
if (props) {
let features = props.features;
if (features) {
let rowName = "";
features.map((f) => {
rowName = Object.keys(f.properties);
});

return (
<thead>
<tr>
<th> </th>
{rowName.map((th) => (
<th> {th.toUpperCase()} </th>
))}
</tr>
</thead>
);
}
}
};

const TableRows = (props) => {
if (props) {
let features = props.features;
if (features) {
let row = "";
features.map((f) => {
row = Object.values(f.properties);
});

return (
<tbody>
{features &&
features.map((f) => (
<tr key={f.id}>
<td>
<ButtonZoom coor={f.geometry.coordinates} />
</td>
{row.map((td) => (
<td> {td} </td>
))}
</tr>
))}
</tbody>
);
}
}
};

class ButtonZoom extends Component {
zoomFeatrue = () => {
Expand All @@ -68,11 +16,8 @@ class ButtonZoom extends Component {
);
}
}

export default class TableList extends Component {

render() {

const { features } = this.props.data;

if (!features) {
Expand All @@ -84,11 +29,29 @@ export default class TableList extends Component {
);
} else {
return (
<table className="table table-striped">
<TableHeader features={features} />
<TableRows features={features} />
<table className="table table-striped">
<thead>
<tr>
<th> </th>
<th>CODMUN</th>
<th>CENTRO</th>
<th>TIPO CENTRO</th>
<th>TITULARIDAD</th>
</tr>
</thead>
<tbody>
{features &&
features.map((f) => (
<tr key={f.id}>
<td> <ButtonZoom coor={f.geometry.coordinates} /> </td>
<td> {f.properties.codmun} </td>
<td> {f.properties.centro} </td>
<td> {f.properties.tipocentro} </td>
<td> {f.properties.titularida} </td>
</tr>
))}
</tbody>
</table>

);
}
}
Expand Down
116 changes: 35 additions & 81 deletions sprint.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,74 +38,7 @@ Los temas aprendidos sobre React a partir del desarrollo de estas tareas son los

En este último componente vamos a **presentar en formato tabla los resultados obtenidos desde el servicio WFS** de la Junta de Andalucía con datos sobre servicios sanitarios. Son los mismos datos que usamos para [añadir el GeoJSON al mapa](http://www.sigdeletras.com/2020/side-project-4-react-y-leaflet-wfs/).

Queremos que sea totalmente reutilizable. Es decir en un futuro desarrollo una funcionalidad que permitiera consultar otra capa de datos, seguramente los atributos (properties) serían distintas respecto a su denominación y número.Para solucionar esto he creado dentro *TableList* dos "subcompontes" funcionales.

El primero llamado *TableHeader* se va a encargar de obtener los nombres de las columnas. La información se encuentra del objeto GeoJSON. He usado la función *map()* para obtener los datos y el método [Object.keys()](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/keys) que devuelve un array de las propiedades *names* del objeto. Los datos los añadimos al elemento *th* dentro de la tabla.

```javascript
//TableList.js
...
const TableHeader = (props) => {
if (props) {
let features = props.features;
if (features) {
let rowName = "";
features.map((f) => {
rowName = Object.keys(f.properties);
});

return (
<thead>
<tr>
<th> </th>
{rowName.map((th) => (
<th> {th.toUpperCase()} </th>
))}
</tr>
</thead>
);
}
}
};

```

Para las filas, seguimos el mismo procedimiento, pero en esta ocasión usamos [Object.values()](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/values) que *"devuelve un array con los valores correspondientes a las propiedades enumerables de un objeto".*

```javascript
//TableList.js
...
const TableRows = (props) => {
if (props) {
let features = props.features;
if (features) {
let row = "";
features.map((f) => {
row = Object.values(f.properties);
});

return (
<tbody>
{features &&
features.map((f) => (
<tr key={f.id}>
<td>
<ButtonZoom coor={f.geometry.coordinates} />
</td>
{row.map((td) => (
<td> {td} </td>
))}
</tr>
))}
</tbody>
);
}
}
};
...
```

El componente *TableList* quedará así.
Para el componente usamos los datos que nos vienen desde sus propiedades y montamos una tabla con cabecera y cuerpo de datos que devuelve la información usando la función map(). El componente *TableList* quedará así.

```javascript
//TablaList
Expand All @@ -114,33 +47,54 @@ export default class TableList extends Component {
render() {
const { features } = this.props.data;

if (!features) {
if (!features) {
return (
<p className="col-12 text-center mt-4 font-weight-bold">
Select a municipality from the list. <br /> Then press the <i>Load</i> button
Select a municipality from the list. <br /> Then press the Load button
to view the results
</p>
);
} else {
return (
<table className="table table-striped">
<TableHeader features={features} />
<TableRows features={features} />
<thead>
<tr>
<th> </th>
<th>CODMUN</th>
<th>CENTRO</th>
<th>TIPO CENTRO</th>
<th>TITULARIDAD</th>
</tr>
</thead>
<tbody>
{features &&
features.map((f) => (
<tr key={f.id}>
<td> <ButtonZoom coor={f.geometry.coordinates} /> </td>
<td> {f.properties.codmun} </td>
<td> {f.properties.centro} </td>
<td> {f.properties.tipocentro} </td>
<td> {f.properties.titularida} </td>
</tr>
))}
</tbody>
</table>
);
}
}
}

Para futuras mejoras, se debería refactorizar el código y que pudiera servir para cualquier tipo de datos temáticos que se consultaran. Ahora mismos está desarrollado pensando en el modelo de datos de servicios sanitarios.

```

# Implementando un botón de zum con el patrón de diseño Pub-Sub.

Es interesante añadir un **bótón que permita hacer zum al elemento dentro desde la tabla**. Para obtener una comunicación directa entre componentes, y que permita usar ejecutar el método *flyTo()* de Leaflet en el compomente *MapView*, he usado el [**patrón de diseño **observador**](https://es.wikipedia.org/wiki/Observer_(patr%C3%B3n_de_dise%C3%B1o))

Es interesante añadir un **bótón que permita hacer zum al elemento dentro desde la tabla**. Para obtener una comunicación directa entre componentes, y que ejecute el método *flyTo()* de Leaflet en el compomente *MapView*, he usado el [**patrón de diseño **Observador**](https://es.wikipedia.org/wiki/Observer_(patr%C3%B3n_de_dise%C3%B1o))

Este patrón permite definir una dependencia de uno a muchos entre objetos, de forma que cuando un objeto (sujeto) cambie de estado se notifique y se actualicen automáticamente todos los objetos (observadores) que depende de él. Esta notificación se realiza normalmente a través de uno de sus métodos.
Este patrón define una dependencia de uno a muchos entre objetos, de forma que cuando un objeto (sujeto) cambie de estado, se notifique y se actualicen automáticamente todos los objetos (observadores) que depende de él. Esta notificación se realiza normalmente a través de uno de sus métodos.

El patrón se ha usado para comunicar dos componentes hijos, en este caso *ButtonZoom* que obtiene las coordenadas desde las propiedades de cada *TableRows* y *MapView* que es donde se encuentra el evento del zum a las coordenadas pasadas.
El patrón se ha usado para comunicar dos componentes hijos, en este caso *ButtonZoom* que obtiene las coordenadas desde las propiedades de cada fila y *MapView* que es donde se encuentra el evento del zum a las coordenadas pasadas.

Para ser más específicos se ha usado el **patrón Pub-Sub(Publisher-Subscriber)** que añade un evento intermedio. La implementación de este patrón se a realizado gracias a la librería [PubSub](https://www.npmjs.com/package/pubsub-js). En esta [entrada](https://medium.com/@Aida_Pro_/observer-vs-eventbus-patrones-de-dise%C3%B1o-cd8178f48c7d) es donde he obtenido la parte teórica sobre el usos de ambos patrones.

Expand Down Expand Up @@ -174,11 +128,11 @@ class ButtonZoom extends Component {
}
}
```
*ButtonZoom* es usado dentro del componente TableRows y tiene como propiedades el array de coordenadas del elemento.
*ButtonZoom* es usado dentro del componente *TableList* y tiene como propiedades el array de coordenadas del elemento.

![04_button.png](img/04_button.png)

Ahora vamos a definir los observadores/suscriptores de nuetro evento. En la aplicación será el compomente MapView que es donde podemos usar los métodos de Leaflet gracias al [uso de referencias en React como comentamos en el artículo anterior](http://www.sigdeletras.com/2020/side-project-4-react-y-leaflet-wfs/). La suscripción la hacemos dentro del cliclo de vida *componentDidMount()*. Es importante también eliminar la suscripción ya puede ocurrir fugas de memoria. Esto lo haremos con el método *component WillUnmount()* mediante *PubSub.unsubscribe*.
Vamos a definir los observadores/suscriptores de nuetro evento. En la aplicación será el compomente MapView que es donde podemos usar los métodos de Leaflet gracias al [uso de referencias en React como comentamos en el artículo anterior](http://www.sigdeletras.com/2020/side-project-4-react-y-leaflet-wfs/). La suscripción la hacemos dentro del cliclo de vida *componentDidMount()*. Es importante también eliminar la suscripción ya puede ocurrir fugas de memoria. Esto lo haremos con el método *component WillUnmount()* mediante *PubSub.unsubscribe*.

```javascript
import React from "react";
Expand All @@ -202,9 +156,9 @@ export default class MapView extends React.Component {
})
}

// componentWillUnmount(){
// PubSub.unsubscribe('zoomFromTableRow')
// }
componentWillUnmount(){
PubSub.unsubscribe('zoomFromTableRow')
}
...
```
Expand Down

0 comments on commit cfafa21

Please sign in to comment.