Spanish (Español) translation by Elías Nicolás (you can also view the original English article)
En
la parte anterior de la serie, hemos iniciado nuestra aplicación
AngularJS, configurado el enrutamiento para diferentes vistas, y
construido servicios alrededor de rutas para puestos, usuarios y
categorías. Usando estos servicios, ahora somos capaces finalmente de buscar los datos del servidor para encender el front-end.
En
esta parte de la serie, vamos a trabajar en la construcción de una
directiva personalizada AngularJS para la función de anuncio de correos.
En la parte actual de la serie, vamos a:
- Nos presentamos a las directivas de AngularJS y por qué debemos crear
- Planificar la
directiva para la función de lista de correos y los argumentos que
tomará
- Cree una directiva AngularJS personalizada para la publicación
de anuncios junto con su plantilla
Comencemos por introducirnos en las
directivas de AngularJS y por qué las necesitamos.
Introducción de las
directivas de AngularJS
Las
directivas en AngularJS son una forma de modificar el comportamiento de
los elementos HTML y de reutilizar un fragmento repetible de código.
Pueden ser utilizados para modificar la estructura de un elemento HTML
y sus hijos, y por lo tanto son una manera perfecta de introducir
widgets personalizados de interfaz de usuario.
Al analizar wireframes en
la primera parte de la serie, hemos
observado que la función de lista de correos se está utilizando en tres
vistas, a saber:
- Publicar articulo
- Perfil del autor
- Categoría con listado de articulos
Así
que en lugar de escribir una funcionalidad separada para publicar
mensajes en todas estas tres páginas, podemos crear una directiva
AngularJS personalizada que contenga lógica de negocios para recuperar
publicaciones utilizando los servicios que creamos en la parte anterior
de esta serie. Aparte
de la lógica de negocios, esta directiva también contendrá la lógica de
rendering para incluir los mensajes en ciertas vistas. Es también en
esta directiva que se definirá la funcionalidad para la
post-paginación y recuperación de publicaciones en ciertos criterios.
Por
lo tanto, la creación de una directiva AngularJS personalizada para la
función de publicación de anuncios nos permite definir la funcionalidad
sólo en un lugar y esto nos facilitará ampliar o modificar esta
funcionalidad en el futuro sin tener que cambiar el código en las tres
instancias Donde se está utilizando.
Dicho esto, comencemos a codificar
nuestra directiva personalizada para la función de publicación de articulos.
Planificación de la directiva AngularJS personalizada para la
publicación de articulos
Antes de comenzar a escribir cualquier código
para la construcción de
la directiva para la función de lista de correos, vamos a analizar la
funcionalidad que se necesita en la directiva.
En
el nivel básico, necesitamos una directiva que podamos usar en nuestras
opiniones para la lista de correos, el perfil del autor y la página de
la categoría. Esto significa que estaremos creando un widget
personalizado de
interfaz de usuario (o un marcador DOM) que colocamos en nuestro HTML, y
AngularJS se encargará del resto dependiendo de las opciones que
ofrezcamos para esa instancia particular de la directiva.
Por lo tanto, vamos a crear un widget de interfaz de usuario personalizado identificado por la siguiente etiqueta:
<post-listing></post-listing>
Pero también necesitamos que esta directiva sea flexible, es decir, tomar argumentos como entrada y actuar en consecuencia. Considere
la página de perfil de usuario en la que sólo queremos que aparezcan
los mensajes pertenecientes a ese usuario específico o la página de
categorías en la que aparecerán los mensajes pertenecientes a esa
categoría. Estos argumentos se pueden proporcionar de las dos maneras
siguientes:
- En la URL como parámetros
- Directamente a la
directiva como un valor de atributo
Proporcionar argumentos en la URL parece nativo de la API ya que ya estamos familiarizados con hacerlo. Por lo tanto, un usuario podría recuperar un conjunto de publicaciones pertenecientes a un usuario específico de la siguiente manera
https://127.0.0.1:8080/#/posts?author=1
La funcionalidad anterior se puede lograr utilizando el servicio $routeParams
proporcionado por AngularJS. Aquí es donde podemos acceder a los parámetros proporcionados por el
usuario en la URL. Ya lo hemos analizado al registrar rutas en la parte
anterior de la serie.
En cuanto a proporcionar argumentos directamente a la directiva como un valor de atributo, podríamos usar algo como lo siguiente:
<post-listing post-args="{author=1}"></post-listing>
El
atributo post-args
en el fragmento anterior toma argumentos para
recuperar un conjunto específico de entradas y actualmente toma el ID de
autor. Este atributo puede tomar cualquier número de argumentos para recuperar mensajes como soportados por la ruta /wp/v2/posts
. Así
que si tuviéramos que recuperar un conjunto de posts creado por un
usuario con un ID de 1 y pertenecer a una categoría de ID 10, podríamos
hacer algo como lo siguiente:
<post-listing post-args="{author=1, filter[cat]=10}"></post-listing>
El filter[cat]
parámetro en el código anterior se utiliza para
recuperar un conjunto de puestos pertenecientes a una cierta categoría.
Paginación es también una característica esencial cuando se trabaja con
las páginas de anuncio de la publicación. La
directiva manejará la paginación posterior y esta característica será
impulsada por los valores de los encabezados X-WP-Total
y
X-WP-TotalPages
devueltos por el servidor junto con el cuerpo de la
respuesta. Por lo tanto, el usuario será capaz de navegar hacia adelante
y hacia
atrás entre el anterior y el siguiente conjunto de puestos.
Después de
haber decidido el nitty gritty de la directiva
personalizada para la lista de correos, ahora tenemos una base bastante
sólida para comenzar a escribir el código.
Construyendo una directiva
personalizada para publicar articulos
La construcción de una directiva
para la función de publicación de articulos incluye dos pasos:
- Cree la lógica de negocio para recuperar publicaciones y manejar otras cosas.
- Cree una vista de representación para que estos mensajes se
muestren en la página.
La lógica de negocio de nuestra directiva
personalizada se tratará en la declaración de la directiva. Y para
procesar datos en el DOM, crearemos una plantilla personalizada para
publicar articulos. Comencemos con la declaración de la
directiva.
Declaración de la Directiva
Las directivas en AngularJS se pueden declarar para un módulo con la siguiente sintaxis:
/** * Creating a custom directive for posts listing */ quiescentApp.directive( 'postListing', [function() { return { }; }] );
Aquí estamos declarando una directiva en nuestro módulo usando el método .directive()
que está disponible en el módulo. El
método toma el nombre de la directiva como el primer argumento, y este
nombre está estrechamente vinculado con el nombre de la etiqueta del
elemento. Puesto
que queremos que nuestro elemento HTML sea <post-listing></post-listing>
, ofrecemos
una representación de camel-case del nombre
de la etiqueta. Puede obtener más información sobre este proceso de
normalización
realizado por AngularJS para que coincida con los nombres de directiva
en la documentación oficial.
La
notación que estamos usando en el código anterior para declarar nuestra
directiva se denomina safe-style de la inyección de dependencia. Y en
esta notación, proporcionamos una serie de dependencias como el segundo
argumento que será necesario por la directiva. Actualmente, no hemos
definido ninguna dependencia para nuestra directiva personalizada. Pero
como necesitamos el servicio Posts
para recuperar mensajes (que
creamos en la parte anterior de la serie) y los $routeParams
y $location
de AngularJS nativos para acceder a los parámetros de URL y
la ruta actual, los definimos como sigue:
/** * Creating a custom directive for posts listing */ quiescentApp.directive( 'postListing', ['$routeParams', '$location', 'Posts', function( $routeParams, $location, Posts ) { return { restrict: 'E', scope: { postArgs: '=' }, link: function( $scope, $elem, $attr ) { } }; }] );
Estas dependencias se ponen a disposición de la función que se define como el último elemento de la matriz. Esta función devuelve un objeto que contiene la definición de directiva.
Actualmente, tenemos dos propiedades en el objeto de definición de
directiva, es decir, restrict
y link
.
La opción restrict
define
la forma en que usamos directiva en
nuestro código, y puede haber cuatro valores posibles para esta
opción:
-
A
: Para usar la directiva como un atributo en un elemento HTML existente. -
E
: Para usar la directiva como un nombre de elemento.
-
C
: Para usar la directiva como un nombre de clase.
-
M
: Para usar la directiva como un comentario HTML.
La opción de restrict
también puede aceptar cualquier combinación de los cuatro valores
anteriores.
Puesto
que queremos que nuestra directiva sea un elemento nuevo
<post-listing></post-listing>
, establecemos la opción
restrict en E
. Si definimos la directiva usando los atributos de un
elemento HTML preexistente, Podría haber establecido esta opción en A
. En ese caso, podríamos usar
<div post-listing></div>
para definir la directiva en
nuestro código HTML.
La segunda propiedad scope
se utiliza para
modificar el ámbito de la directiva. De
forma predeterminada, el valor de la propiedad scope
es false
, lo que
significa que el ámbito de la directiva es el mismo que el de su padre. Cuando
se pasa un objeto, se crea un ámbito aislado para la directiva y
cualquier dato que se debe pasar a la directiva por su padre se pasa a
través de atributos HTML. Esto es lo que estamos haciendo en nuestro
código, y el atributo que estamos usando es post-args
, que se normaliza
en postArgs
.
La propiedad postArgs
en el objeto scope
puede aceptar
cualquiera de los siguientes tres valores:
-
=
: Significa que el valor pasado en el atributo sería tratado como un objeto. -
@
: Significa que el valor pasado en el atributo sería tratado como una cadena simple.
-
&
: Significando que el valor pasado en el atributo sería tratado como una función.
Dado que hemos elegido utilizar el valor =
,
cualquier valor que se
pasa en el atributo post-args
sería tratado como un objeto JSON, y
podríamos utilizar ese objeto como argumento para recuperar las
entradas.
La
tercera propiedad, link
, se utiliza para definir una función que se
utiliza para manipular el DOM y definir API y funciones que son
necesarias para la directiva. Esta función es donde se maneja toda la
lógica de la directiva.
La
función de link
acepta argumentos para el objeto de ámbito, el
elemento HTML de la directiva y un objeto para los atributos definidos
en el elemento HTML de la directiva. Actualmente, estamos pasando dos
argumentos $scope
y $elem
para el objeto scope y el elemento HTML
respectivamente.
Vamos
a definir algunas variables en la propiedad $scope
que vamos a
utilizar para procesar la función de anuncio de la publicación en el
DOM.
/** * Creating a custom directive for posts listing */ quiescentApp.directive( 'postListing', ['$routeParams', '$location', 'Posts', function( $routeParams, $location, Posts ) { return { restrict: 'E', scope: { postArgs: '=' }, link: function( $scope, $elem, $attr ) { // defining variables on the $scope object $scope.posts = []; $scope.postHeaders = {}; $scope.currentPage = $routeParams.page ? Math.abs( $routeParams.page ) : 1; $scope.nextPage = null; $scope.previousPage = null; $scope.routeContext = $location.path(); } }; }] );
Por lo tanto, hemos definido seis propiedades en el objeto $scope
que podríamos tener acceso en el DOM. Estas propiedades son:
-
$posts
: Una matriz para retener los objetos del puesto que serán devueltos por el servidor. -
$postHeaders
: Un objeto para mantener los encabezados que serán devueltos por el servidor junto con el cuerpo de respuesta. Los usaremos para manejar la navegación.
-
$currentPage
: Una variable entera que contiene el número de página actual.
-
$previousPage
: Una variable que contiene el número de página anterior.
-
$nextPage
: Una variable que contiene el siguiente número de página.
-
$routeContext
: Para acceder a la ruta actual utilizando el servicio$location
.
La propiedad postArgs
que definimos anteriormente
para atributos HTML
ya estará disponible en el objeto $scope
dentro de la directiva.
Ahora
estamos listos para hacer una solicitud al servidor usando el servicio
Posts
para recuperar mensajes. Pero
antes de eso, debemos tener en cuenta los argumentos proporcionados por
el usuario como parámetros de URL, así como los parámetros
proporcionados en el atributo post-args
. Y
para ese propósito, crearemos una función que utiliza el servicio $routeParams
para extraer los parámetros de URL y fusionarlos con los
argumentos proporcionados a través del atributo post-args
:
/** * Creating a custom directive for posts listing */ quiescentApp.directive( 'postListing', ['$routeParams', '$location', 'Posts', function( $routeParams, $location, Posts ) { return { restrict: 'E', scope: { postArgs: '=' }, link: function( $scope, $elem, $attr ) { // defining variables on the $scope object $scope.posts = []; $scope.postHeaders = {}; $scope.currentPage = $routeParams.page ? Math.abs( $routeParams.page ) : 1; $scope.nextPage = null; $scope.previousPage = null; $scope.routeContext = $location.path(); // preparing query arguments var prepareQueryArgs = function() { var tempParams = $routeParams; delete tempParams.id; return angular.merge( {}, $scope.postArgs, tempParams ); }; } }; }] );
El método
prepareQueryArgs()
en el código anterior utiliza el método
angular.merge()
, que extiende el objeto $scope.postArgs
con el objeto $routeParams
. Pero antes de fusionar estos dos objetos,
primero elimina la propiedad id
del objeto $routeParams
utilizando el
operador delete
. Esto es necesario ya que usaremos esta
directiva en las vistas de categoría y de usuario, y no queremos que la
categoría y los ID de usuario se interpreten falsamente como la ID
postal.
Habiendo preparado los argumentos
de consulta, finalmente estamos listos para hacer una llamada al
servidor y recuperar mensajes, y lo hacemos con el método Posts.query ()
, que toma dos argumentos:
- Objeto que contiene argumentos para realizar la consulta.
- Una función de devolución de llamada que se
ejecuta después de que la consulta se ha completado.
Así
que usaremos la función prepareQueryArgs()
para preparar un objeto
para los argumentos de consulta, y en la función callback, establecemos
los valores de ciertas variables en la propiedad $scope
:
// make the request and query posts Posts.query( prepareQueryArgs(), function( data, headers ) { $scope.posts = data; $scope.postHeaders = headers(); $scope.previousPage = ( ( $scope.currentPage + 1 ) > $scope.postHeaders['x-wp-totalpages'] ) ? null : ( $scope.currentPage + 1 ); $scope.nextPage = ( ( $scope.currentPage - 1 ) > 0 ) ? ( $scope.currentPage - 1 ) : null; });
La función de devolución de llamada obtiene dos argumentos para el cuerpo de respuesta y los encabezados de respuesta. Éstos se representan respectivamente por los argumentos de datos data
y encabezados headers
.
El argumento headers
es una función que devuelve un objeto que contiene
los encabezados de respuesta por el servidor.
El código restante es
bastante auto-explicativo como estamos estableciendo el valor de la
matriz $scope.posts
. Para
establecer los valores de las variables $scope.previousPage
y $scope.nextPage
, estamos usando la propiedad x-wp-totalpages
en el objeto
postHeaders
.
Y ahora estamos listos para
procesar estos datos en la parte frontal utilizando una plantilla
personalizada para nuestra directiva.
Creación de una plantilla
personalizada para la directiva
Lo
último que tenemos que hacer para hacer que nuestra directiva funcione
es hacer una plantilla separada para la lista de correos y vincularla a
la directiva. Para ello, necesitamos modificar la declaración de la
directiva e incluir una propiedad templateUrl
como la siguiente:
/** * Creating a custom directive for posts listing */ quiescentApp.directive( 'postListing', ['$routeParams', '$location', 'Posts', function( $routeParams, $location, Posts ) { return { restrict: 'E', scope: { postArgs: '=' }, templateUrl: 'views/directive-post-listing.html', link: function( $scope, $elem, $attr ) { } }; }] );
Esta
propiedad templateUrl
en el código anterior se refiere a un archivo
denominado directive-post-listing.html en el directorio views. Así que crear este archivo en la carpeta de views y pegar en el código HTML siguiente:
<!-- post listing starts --> <article class="post-entry"> <h2 class="post-title"><a href="post-single.html">Good design is a lot like clear thinking made visual.</a></h2> <figure class="post-thumbnail"> <img src="img/img-712-348.jpg" alt="Featured Image"> </figure> <p class="post-meta"> By <a href="author.html">Bilal Shahid</a> in <a href="category.html">Quotes</a> </p> <div class="post-content"> <p>Created days forth. Dominion. Subdue very hath spirit us sixth fish creepeth also. First meat one forth above. You'll Fill for. Can't evening one lights won't. Great of make firmament image. Life his beginning blessed lesser meat spirit blessed seas created green great beginning can't doesn't void moving. Subdue evening make spirit lesser greater all living green firmament winged saw tree one divide wherein divided shall dry very lesser saw, earth the. Light their the.</p> </div> </article> <!-- post listing ends --> <!-- pagination links start --> <div class="post-pagination"> <a href="#" class="button">Older Posts</a> <a href="#" class="button">Newer Posts</a> </div> <!-- pagination links end -->
Este es un código HTML muy básico que representa una sola entrada de entrada y una paginación posterior. Lo he copiado del archivo views/listing.html. Utilizaremos
algunas directivas de AngularJS, incluyendo ng-repeat
, ng-href
, ng-src
y
ng-bind-html
, para mostrar los datos que actualmente residen en la
propiedad $scope
de la directiva.Modifique el código HTML a lo siguiente:
Modifique el código HTML a lo siguiente:
<!-- post listing starts --> <article class="post-entry" ng-repeat="post in posts"> <h2 class="post-title"><a ng-href="#/posts/{{post.slug}}">{{post.title.rendered}}</a></h2> <figure class="post-thumbnail" ng-show="post.quiescent_featured_image"> <img ng-src="{{post.quiescent_featured_image}}" alt="Featured Image"> </figure> <p class="post-meta"> By <a ng-href="#/users/{{post.author}}">{{post.quiescent_author_name}}</a> in <a ng-href="#/categories/{{category.term_id}}" ng-repeat="category in post.quiescent_categories">{{category.name}}{{$last ? '' : ', '}}</a> </p> <div class="post-content" ng-bind-html="post.excerpt.rendered"></div> </article> <!-- post listing ends -->
El código anterior utiliza la directiva ng-repeat
para iterar a través de la matriz $scope.posts
. Cualquier
propiedad que se define en el objeto $scope
en la declaración de
directiva está disponible directamente en la plantilla. Por lo tanto,
nos referimos a la matriz $scope.posts
directamente como posts
en la
plantilla.
Mediante
el uso de la directiva ng-repeat
, nos aseguramos de que el contenedor
article.post-entry
se repita para cada puesto en la matriz posts
y cada
puesto se denomina post
en el bucle interno. Este objeto de
post
contiene datos en el formato JSON devueltos por el servidor, que
contienen propiedades como el título de la publicación, la ID de la
publicación, el contenido de la publicación y el enlace de la imagen
destacada, que es un campo adicional añadido por el complemento
complementario.
En el paso siguiente, reemplazamos
valores como el título de la publicación, el enlace de la publicación y
el vínculo de la imagen destacada con las propiedades del objeto de
publicación post
.
Para la paginación, reemplace el código anterior por lo siguiente:
<!-- pagination links start --> <div class="post-pagination"> <a ng-href="#{{routeContext}}?page={{nextPage}}" class="button" ng-class="{'disabled': !nextPage}">Newer Posts</a> <a ng-href="#{{routeContext}}?page={{previousPage}}" class="button" ng-class="{'disabled': !previousPage}">Older Posts</a> </div> <!-- pagination links end -->
Primero
accedemos a la propiedad routeContext
, que definimos en nuestra
declaración de directiva, y lo sufijo con el parámetro ?Page=
y
utilizamos los valores de las variables nextPage
y previousPage
para navegar
hacia adelante y hacia atrás entre posts. También verificamos si la siguiente página o el enlace de la página
anterior no es nulo null
, de lo contrario agregamos una clase .disabled
al
botón que es proporcionado por Zurb Foundation.
Ahora que hemos terminado la directiva, es hora de probarla. Y
lo hacemos colocando una etiqueta <post-listing></post-listing>
en nuestro HTML, idealmente justo encima de la etiqueta
<footer></footer>
. Hacerlo significa que aparecerá una lista de publicaciones
por encima del pie de página. No se preocupe por el formato y los
estilos, ya que trataremos con ellos en la siguiente parte de la
serie.
Así que es más o menos para crear una directiva personalizada
AngularJS para la función de listado de publicaciones.
¿Qué pasa después?
En
la parte actual de la serie sobre la creación de un front-end con el WP
REST API y AngularJS, construimos una directiva AngularJS personalizada
para la función de lista de publicaciones. Esta directiva utiliza el servicio
Posts
que creamos en la parte anterior de la serie. La directiva
también toma la entrada del usuario en forma de un atributo HTML y
mediante parámetros de URL.
En
la parte final de la serie, comenzaremos a trabajar en la pieza final
de nuestro proyecto, es decir, controladores para puestos, usuarios y
categorías, y sus respectivas plantillas.
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post