Cree una aplicación angular aprovechando las capacidades sin cabeza de Sitefinity

enero 30, 2019 Experiencia Digital, Sitefinity

En este tutorial, aprenda a crear una aplicación Angular que consuma los servicios OData de Sitefinity CMS mediante el SDK OData fácil de usar de Sitefinity.

Sitefinity CMS proporciona potentes capacidades de administración de contenido y API sólidas para consumir contenido a través de los servicios OData, lo que le permite implementar casos de uso de CMS sin cabeza. En tales escenarios, usted crea y organiza su contenido a través de Sitefinity CMS, y lo expone utilizando la API RESTFul lista para usar. Este enfoque le permite desarrollar y entregar este contenido en varios dispositivos y aprovechar los marcos de frontend más populares.

En esta publicación se muestra cómo crear una aplicación Angular que consume los servicios OData de Sitefinity CMS. No tiene que estar demasiado familiarizado con las solicitudes HTTP o el protocolo OData, ya que usaremos el SDK OData de Sitefinity (también conocido a continuación como WebServices SDK). El SDK está disponible a través de npm y tiene una API simple y completa. Estaremos en constante evolución del SDK en 2019 con más mejoras funcionales y de documentación.

Prerrequisitos

  1. Nuestra aplicación consume datos de una instancia de SITEfinity CMS. En este ejemplo, estamos utilizando un sitio web de prueba alojado de Sitefinity (Sandbox). Si no tiene uno, crearlo solo requiere unos pocos clics. Empieza aquí: https://www.progress.com/sitefinity-cms/try-now/sandbox.
  2. Nodo.js 8.10+
  3. CLI angular (https://github.com/angular/angular-cli/wiki)
  4. El código fuente completo de la aplicación que estamos discutiendo se puede encontrar aquí: https://github.com/Sitefinity/QuantumHeadlessAngularApp

Configuración inicial

  1. Comience creando una nueva aplicación Angular y dándole un nombre
     ng new QuantumHeadlessAngularApp
  2. Agregue sitefinity-webservices-sdk como una dependencia npm e instálelo.

    npm install  sitefinity-webservices-sdk --save
  3. Agregue una referencia al javascript sitefinity-webservices-sdk en angular.json.
    "scripts":[ 
      "node_modules/sitefinity-webservices-sdk/dist/sitefinity-webservices-sdk.js" 
    ]
  4. Agregue sitefinity-webservices-sdk como proveedor.
    providers:[ 
      { provide:'Sitefinity', useValue: window['Sitefinity']}, 
    ]

Crear el servicio Sitefinity

El servicio Sitefinity proporciona instancias únicas del objeto Sitefinity SDK y el objeto de consulta SDK. Inyectamos Sitefinity en el constructor del servicio e inicializamos la instancia. Se necesita un serviceUrl , que apunte al servicio OData predeterminado de su proyecto Sitefinity hospedado. La URL del servicio se construye añadiendo /appi/default a su dominio del sitio web de Sitefinity. Por ejemplo:
http://site17899124552543.srv06.sandbox.sitefinity.com/api/default/

import{Inject, Injectable}from'@angular/core';
import{SettingsService}from'./settings.service';

const endpoint = '/api/default/'; @Inyectable({ providedIn: 'root'})export class SitefinityService {private sitefinity: any; private queryInstance: cualquiera; get instance(): any {if(! este. sitefinity) {este. initializeInstance(); }devuelve estearchivo . sitefinity; }get query(): any {devuelve esto. queryInstance; }constructor(@Inject('Sitefinity') private sf, private settings: SettingsService) {}private initializeInstance(){const serviceUrl = '${this. configuración. url}${endpoint}'; if(serviceUrl) {este. sitefinity = nuevo este. sf({serviceUrl}); este. queryInstance = nuevo este. sf. Consulta(); }}}

Crear la aplicación

La aplicación consta de un menú de navegación y dos páginas:Noticias y Showcases.

La página Noticias muestra una lista de noticias. La funcionalidad adicional proporciona a los usuarios la capacidad de cargar más contenido y filtrarlo por taxonomía (etiquetas y categorías).

La segunda página muestra una lista de showcases (donde showcases es un tipo de contenido dinámico que creamos en la prueba alojada). Los usuarios podrán buscar noticias, vitrinas e imágenes.

El diseño general de la aplicación y sus partes reutilizables se encuentran en el layout.component archivo . La plantilla de la layout.component consiste en una navegación, una barra de búsqueda, una imagen de encabezado y un contenedor para diferentes contenidos en las páginas. Aquí hay un breve resumen de la funcionalidad contenida en cada componente:

  • La navegación utiliza el mecanismo de enrutamiento angular
  • La barra de búsqueda es un componente independiente
  • El contenedor es una salida de enrutador angular, que muestra el contenido, dependiendo de la ruta actual.
  • Las imágenes de encabezado también son dinámicas

Visualización de noticias

NewsItemsComponentMuestra una lista de noticias. Una vez inicializado el componente, llamamos al getNewsItems método para cargar la lista.

ngOnInit(){ 
  this.getNewsItems(); 
}

En el getNewsItems método del servicio NewsItems puede ver cómo obtener newsItems de Sitefinity, mediante el SDK de WebServices.

getNewsItems(): Observable<NewsItem[]>{ 
  let query; 
  const=newReplaySubject<NewsItem[]>(1); 
    =this.sitefinity 
      .query 
      .select('Title','Id','Content','DateCreated','PublicationDate','Summary','UrlName','Author','Tags','Category','Featured') 
      .
expand('Miniatura'). orden(«PublicationDate desc»); este. sitefinity. instancia. data(newsItemsDataOptions). obtener({ query: query,successCb: data => newsReplaySubject. siguiente(datos. value as NewsItem[]),failureCb: data => console. registro(datos)}); volver noticiasReplaySubject. asObservable(); }

OData admite varios tipos de opciones de consulta para consultar datos. Los parámetros de consulta le dan la opción de modificar su solicitud con pares clave-valor. La implementación de la consulta, proveniente del SDK de Sitefinity WebServices, simplifica esta sintaxis, por lo que puede usar métodos como seleccionar, expandir, ordenar, dónde, etc. Por ejemplo, en nuestro getNewsItems método, utilizamos la consulta Sitefinity para seleccionar las propiedades deseadas que se devolverán, obtener los elementos de datos relacionados y especificar el orden de los resultados. Dado que la propiedad Thumbnail es un campo relacionado, usamos el método expand para rellenar su valor.

La instancia del objeto Sitefinity se puede configurar utilizando el objeto de datos, donde pasamos información sobre el tipo de contenido, el proveedor y la cultura.

exportconst={ 
  urlName:'newsitems', 
  providerName:'OpenAccessDataProvider', 
  cultureName:'en' 
};

Volviendo al NewsComponent , inyectamos el NewsService en el constructor. En la implementación del getNewsItems método nos suscribimos al getNewsItems método del NewsService . Asignamos las noticias recuperadas a una propiedad pública de la NewsItems clase, para que podamos usarla en la plantilla del componente.

this.=this.newsService.getAllNews().
subscribe((data: NewsItem[]) = > {if (data) {this. noticiasArtículos. push(datos); }});

Agregar la opción Cargar más

Para implementar una funcionalidad Cargar más, ampliamos la consulta con los métodos skip y take.

=this.sitefinity 
  .query 
  .select('Title','Id','Content','DateCreated','PublicationDate','Summary','UrlName','Author','Tags','Category','Featured') 
  .expand('Thumbnail') 
  .order('PublicationDate desc') 
  .skip(skip).take(take);

Así es como debería ser la implementación del método final getNewsItems de nuestro servicio:

getNewsItems(take?:number, skip?:number): Observable<NewsItem[]>{ 
  let query; 
  const=newReplaySubject<NewsItem[]>(1); 
  if((!==null
&& take !== undefined) && (skip !== null && skip !== undefined)) { query = este. sitefinity . consulta . seleccionar('Título', 'Id', 'Contenido', 'FechaCreada', 'PublicationDate', 'Resumen', 'UrlName', 'Autor', 'Etiquetas', 'Categoría', 'Destacado'). expand('Miniatura'). orden('PublicationDate desc'). saltar(omitir). tomar(tomar); } else { query = este. sitefinity . consulta . seleccionar('Título', 'Id', 'Contenido', 'FechaCreada', 'PublicationDate', 'Resumen', 'UrlName', 'Autor','Etiquetas', 'Categoría', 'Destacado'). expand('Miniatura'). orden(«PublicationDate desc»); }este. sitefinity. instancia. data(newsItemsDataOptions). obtener({ query: query,successCb: data => newsReplaySubject. siguiente(datos. value as NewsItem[]),failureCb: data => console. registro(datos)}); volver noticiasReplaySubject. asObservable(); }

Implementar la obtención de un solo elemento

La obtención de un único newsItem con el SDK se realiza mediante el getSingle método de la instancia. Así es como obtenemos un newsItem por id en el NewsService archivo .

getNewsItem(id:string): Observable<NewsItem>{ 
  const=newReplaySubject<any>(1); 
    this.sitefinity.instance.data(newsItemsDataOptions).getSingle({ 
        key: id, 
        query:this.sitefinity 
          .query 
          .select('Title','Id','Content','DateCreated','Summary','UrlName','Author','Tags') 
          .expand('Thumbnail') 
          .order('Title desc'), 
successCb: (data: NewsItem) => {newsReplaySubject. next(data)},failureCb: data => console. registro(datos)}); volver noticiasReplaySubject. asObservable(); }

Agregar filtrado por taxonomía

En la página de Noticias, también podemos filtrar por etiqueta y por categoría. Hacemos esto implementando un getNewsByTaxa método del , donde NewsService propertyName es el nombre del campo de taxonomía (por ejemplo, "Etiquetas" o "Categoría") y taxaId es el Id de la taxonomía por la que estamos filtrando.

getNewsByTaxa(propertyName:string, taxaId:string): Observable<NewsItem[]>{ 
  const=newReplaySubject<any>(1); 
  this.sitefinity.instance.data(newsItemsDataOptions).get({ 
    query:this.sitefinity 
      .query 
      .select('Title','Id','Content','DateCreated','Summary','UrlName','Author') 
      .expand('Thumbnail') 
      .order('Title desc') 
      .where() 
. cualquiera(). eq(propertyName, taxaId). hecho(). done(),successCb: data => newsSubject. siguiente(datos. value as NewsItem[]),failureCb: data => console. registro(datos)}); volver noticiasSujeto. asObservable(); }

Observe cómo estamos utilizando el método where de la consulta Sitefinity en la getNewsByTaxa implementación. La sintaxis es sencilla y admite operaciones de filtrado estándar.

Tenga en cuenta el doble uso del done() método, que es necesario porque la última llamada al mismo finaliza la definición de la consulta actual. Еach operador lógico (por ejemplo, eq, y, o, contiene, etc.) requiere volver a llamar al método done. Esto es específico de la implementación actual del SDK de Sitefinity OData y está sujeto a refactorización en las versiones futuras, donde solo se necesitará una llamada done() a.

.where() 
.any() 
.eq(propertyName, taxaId) 
.done().done()

Obtener el recuento total de artículos (sin buscar los artículos)

El último método que tenemos en el servicio de Noticias es:

getAllNewsCount(): Observable<number>{ 
  const=newReplaySubject<any>(1); 
    this.sitefinity.instance.
data(newsItemsDataOptions). obtener({ consulta: este. sitefinity . consulta . count(false),successCb: (data: number) => newsReplaySubject. next(data),failureCb: data => consola. registro(datos)}); volver noticiasReplaySubject. asObservable(); }

De forma predeterminada, el método count devuelve todos los elementos, así como su recuento. Sin embargo, al pasar false como argumento, el método devuelve sólo el recuento. En nuestra aplicación utilizamos este método para comprobar cuándo se debe mostrar el enlace Mostrar más.

Implementar la funcionalidad de búsqueda

Otra parte importante de la aplicación es la funcionalidad de búsqueda. Queremos buscar en múltiples tipos de contenido: imágenes, vitrinas y noticias. Para esto utilizamos la funcionalidad de solicitud por lotes del SDK, que nos permite combinar múltiples solicitudes HTTP en una.

privategetItemsBySearchWord(searchWord:string):void{ 
  const=this.sitefinity.instance.batch(data=>this._searchResults.next(this.mapSearchResults(data))); 
  batch.get({ entitySet:'showcases', query:this.sitefinity 
      .query 
      .
seleccione('Título', 'Cliente', 'Desafío', 'Solución', 'Resultados', 'Id'). orden('Título asc'). donde(). o(). contiene('Título', searchWord). o(). contiene('Cliente', searchWord). o(). contiene('Desafío', searchWord). o(). contiene('Solución', searchWord). o(). contiene('Resultados', searchWord). hecho(). hecho(). hecho(). hecho(). hecho(). hecho()}); lote. get({ entitySet: 'images', query: this. sitefinity . consulta . donde(). contiene('Título', searchWord). hecho()}); lote. get({ entitySet: 'newsitems', query: this. sitefinity . consulta . seleccione('Título', 'Contenido', 'Resumen', 'Id'). orden('Título asc'). donde(). o(). contiene('Título', searchWord). o(). contiene('Contenido', searchWord). o(). contiene('Resumen', searchWord). hecho(). hecho(). hecho(). hecho()}); lote. ejecutar(); }

Para encadenar las solicitudes, creamos una instancia de un nuevo lote desde la instancia de Sitefinity, pasando una devolución de llamada para el resultado. A continuación, llamamos al método get del objeto batch para cada tipo de contenido que nos gustaría solicitar. Para finalizar la solicitud por lotes, utilizamos el batch.execute() método.

Esperamos que esta publicación de blog lo haya ayudado a comenzar con los servicios OData de Sitefinity y que haya disfrutado trabajando con el SDK. Si tiene alguna pregunta, envíenos una línea en la sección de comentarios a continuación. Si eres nuevo en Sitefinity, puedes obtener más información aquí o saltar directamente y comenzar tu prueba gratuita de 30 días hoy.

¿Necesita ponerse al día con Sitefinity? Regístrese en nuestro curso gratuito diseñado para ayudar a los aspirantes a desarrolladores a aprovechar todo el potencial de Sitefinity.