Trabajar con datos de web de host de JavaScript en la web de complemento
Este es el undécimo artículo de una serie sobre los conceptos básicos de desarrollo de complementos de SharePoint hospedados en SharePoint. Primero debe familiarizarse con Complementos de SharePoint y con los anteriores artículos de esta serie, los cuales puede encontrar en Introducción a la creación de complementos de SharePoint hospedados en SharePoint | Pasos siguientes.
Nota:
Si ha estado trabajando en esta serie sobre complementos hospedados por SharePoint, hay una solución de Visual Studio que puede usar para continuar con este tema. También puede descargar el repositorio que encontrará en SharePoint_SP-hosted_Add-Ins_Tutorials y abrir el archivo BeforeHostWebData.sln.
De forma predeterminada, SharePoint está diseñado para impedir que el código JavaScript de un complemento acceda a los datos de otros sitios web de SharePoint en la granja. Esto impide que el script de un complemento acceda a datos confidenciales. A menudo, sin embargo, un complemento necesita acceder a la web de host o a otros sitios web de la misma colección de sitios como a la web de host.
Hay dos formas de habilitar este escenario en el complemento:
- Debe solicitar permiso a la web de host en el archivo de manifiesto de su complemento. Se pedirá al usuario que instala el complemento que conceda este permiso; si no lo concede, el complemento no se podrá instalar.
- En vez de usar un objeto SP.ClientContext para hacer llamadas JSOM a la web de host, use un objeto SP.AppContextSite. Este objeto permite que el complemento obtenga un objeto de contexto para sitios web que no sean la web del complemento, pero solo para los sitios web de la misma colección de sitios. También hay una forma de obtener acceso a cualquier sitio web de la suscripción a SharePoint Online (o a una aplicación web de SharePoint local), pero se trata de una cuestión de nivel avanzado.
En este artículo se usa el JSOM para buscar las orientaciones que aún no se iniciaron y asegurarse de que se programan en un calendario en la web de host.
Preparar el calendario de la web de host
Abra la web de host (su sitio web de prueba para desarrolladores) y busque un calendario con el nombre Programa de orientación para empleados que tiene un único evento: Orientar a Claudia Olivares. Si no encuentra el calendario, siga estos pasos:
En la página principal del sitio, seleccione Contenido del sitio>Agregar un complemento>Calendario.
En el cuadro de diálogo Agregar un calendario, escriba Programa de orientación para empleados como Nombre y, después, seleccione Crear.
Cuando se abra el calendario, coloque el cursor sobre cualquier fecha hasta que se muestre el vínculo Agregar sobre la fecha y, después, seleccione Agregar.
En el cuadro de diálogo Programa de orientación para empleados: nuevo elemento, escriba Orientar a Claudia Olivares en Título. Deje los demás campos en sus valores predeterminados y seleccione Guardar.
El calendario será similar al siguiente:
Figura 1. Calendario personalizado
Crear el código de JavaScript y un botón que lo invoca
Abra el archivo Add-in.js en el nodo Scripts del Explorador de soluciones.
Agregue las declaraciones siguientes debajo de la declaración de
completedItems
.var notStartedItems; var calendarList; var scheduledItems;
notStartedItems
hace referencia a los elementos de la lista Nuevos empleados de Seattle cuya Fase de orientación sea No iniciada.calendarList
hace referencia al calendario que creó en la web de host.scheduledItems
hace referencia a una colección de elementos en el calendario.
Cuando se ejecuta un complemento de SharePoint, SharePoint llama a su página de inicio y agrega algunos parámetros de consulta a la dirección URL de la página de inicio. Uno de ellos es
SPHostUrl
, que es la dirección URL de la web de host. El complemento necesita esta información para realizar llamadas a datos de web de host, así que cerca de la parte superior del archivo Add-in.js, justo debajo de la declaración de variables parascheduledItems
, agregue la línea siguiente:var hostWebURL = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
Tenga en cuenta lo siguiente en relación con este código:
getQueryStringParameter
es una función de utilidad que creará en el paso siguiente.decodeUriComponent
es una función de JavaScript estándar que revierte la codificación de URI que SharePoint realiza en los parámetros de consulta. Por ejemplo, una diagonal codificada, "%2F", se cambia por "/".
Agregue el siguiente código en la parte final del archivo. Esta función puede usarse para leer los parámetros de consulta.
// Utility functions function getQueryStringParameter(paramToRetrieve) { var params = document.URL.split("?")[1].split("&"); var strParams = ""; for (var i = 0; i < params.length; i = i + 1) { var singleParam = params[i].split("="); if (singleParam[0] == paramToRetrieve) { return singleParam[1]; } } }
Agregue la función siguiente al archivo Add-in.js en alguna ubicación por encima de la sección de devoluciones de llamada de errores.
function ensureOrientationScheduling() { var camlQuery = new SP.CamlQuery(); camlQuery.set_viewXml( '<View><Query><Where><Eq>' + '<FieldRef Name=\'OrientationStage\'/><Value Type=\'Choice\'>Not started</Value>' + '</Eq></Where></Query></View>'); notStartedItems = employeeList.getItems(camlQuery); clientContext.load(notStartedItems); clientContext.executeQueryAsync(getScheduledOrientations, onGetNotStartedItemsFail); return false; }
Tenga en cuenta lo siguiente en relación con este código:
- Es casi idéntico al método de lista de consultas que obtiene los elementos Completados, excepto por el hecho de que obtiene elementos con el estado No iniciados en vez de los que están Completados. Nos interesan solo los elementos No iniciados porque el script presupone, para simplificar, que si una orientación pasa la fase No iniciado, ya debe estar programada.
- Creará dos métodos de devolución de llamada en la llamada executeQueryAsync en pasos posteriores.
Agregue la siguiente función al archivo Add-in.js, justo debajo de la función anterior. Tenga en cuenta que usa el objeto hostWebContext para identificar la lista que se consulta.
function getScheduledOrientations() { var hostWebContext = new SP.AppContextSite(clientContext, hostWebURL); calendarList = hostWebContext.get_web().get_lists().getByTitle('Employee Orientation Schedule'); var camlQuery = new SP.CamlQuery(); scheduledItems = calendarList.getItems(camlQuery); clientContext.load(scheduledItems); clientContext.executeQueryAsync(scheduleAsNeeded, onGetScheduledItemsFail); }
Nota:
Tenga en cuenta que no se añade ningún marcado a la consulta CAML. La finalidad de no tener una consulta real en el objeto de la consulta es garantizar la recuperación de todos los elementos de la lista. Si la lista es muy larga, la solicitud al servidor puede tardar demasiado en ejecutarse. En ese caso, nos interesaría encontrar otra forma de lograr nuestro objetivo. Pero en esta situación de ejemplo, en la que tenemos una lista muy corta (y las listas de calendario casi siempre son cortas), obtener la lista completa para que podamos iterarla en el cliente nos ayudará a minimizar el número de llamadas de executeQueryAsync al servidor.
Agregue la siguiente función al archivo.
function scheduleAsNeeded() { var unscheduledItems = false; var dayOfMonth = '10'; var listItemEnumerator = notStartedItems.getEnumerator(); while (listItemEnumerator.moveNext()) { var alreadyScheduled = false; var notStartedItem = listItemEnumerator.get_current(); var calendarEventEnumerator = scheduledItems.getEnumerator(); while (calendarEventEnumerator.moveNext()) { var scheduledEvent = calendarEventEnumerator.get_current(); // The SP.ListItem.get_item('field_name ') method gets the value of the specified field. if (scheduledEvent.get_item('Title').indexOf(notStartedItem.get_item('Title')) > -1) { alreadyScheduled = true; break; } } if (alreadyScheduled === false) { // SP.ListItemCreationInformation holds the information the SharePoint server needs to // create a list item var calendarItem = new SP.ListItemCreationInformation(); // The some_list .additem method tells the server which list to add // the item to. var itemToCreate = calendarList.addItem(calendarItem); // The some_item .set_item method sets the value of the specified field. itemToCreate.set_item('Title', 'Orient ' + notStartedItem.get_item('Title')); // The EventDate and EndDate are the start and stop times of an event. itemToCreate.set_item('EventDate', '2015-06-' + dayOfMonth + 'T21:00:00Z'); itemToCreate.set_item('EndDate', '2015-06-' + dayOfMonth + 'T23:00:00Z'); dayOfMonth++; // The update method tells the server to commit the changes to the SharePoint database. itemToCreate.update(); unscheduledItems = true; } } if (unscheduledItems) { calendarList.update(); clientContext.executeQueryAsync(onScheduleItemsSuccess, onScheduleItemsFail); } }
Tenga en cuenta lo siguiente en relación con este código:
El método comprueba si el título de un elemento No iniciado de la lista Nuevos empleados de Seattle, que es el nombre de un empleado, se encuentra en el título de un evento del calendario Programa de orientación para empleados. Por lo tanto, se presupone (para simplificar) que todas las entradas del calendario se crean con el nombre completo del empleado en el título del evento.
Si ninguno de los eventos que ya están en el calendario coincide con un elemento No iniciado, el script crea un elemento de calendario para el elemento No iniciado.
JSOM usa un objeto ListItemCreationInformation ligero, en lugar de un objeto SPListItem para reducir el tamaño de la carga que se envía al servidor de SharePoint.
Los dos campos DateTime del evento de calendario nuevo están establecidos en los días del mes en que se escribió este artículo:
2015-06
. Para no tener que desplazarse hacia atrás en el calendario para buscar los elementos, cambie estas fechas por un día del mes y año actuales.Si se encuentra que hay elementos No iniciados sin programar, el primero se programará para el día 10 del mes. Cada elemento adicional no programado se programará para un día después. Se presupone para simplificar que no habrá tantos como para programarse para días imposibles del mes, por ejemplo, "32".
La mayor parte de este código es JavaScript estándar. Hay comentarios en las líneas que usan JSOM de SharePoint.
Agregue el siguiente controlador de éxito que se llama cuando se agregan al calendario los elementos sin programar previamente.
function onScheduleItemsSuccess() { alert('There was one or more unscheduled orientations and they have been added to the ' + 'Employee Orientation Schedule calendar.'); }
Agregue las siguientes funciones de error a la sección de devoluciones de llamada de errores del archivo.
function onGetNotStartedItemsFail(sender, args) { alert('Unable to get the not-started items. Error:' + args.get_message() + '\n' + args.get_stackTrace()); } function onGetScheduledItemsFail(sender, args) { alert('Unable to get scheduled items from host web. Error:' + args.get_message() + '\n' + args.get_stackTrace()); } function onScheduleItemsFail(sender, args) { alert('Unable to schedule items on host web calendar. Error:' + args.get_message() + '\n' + args.get_stackTrace()); }
Abra el archivo default.aspx y busque el elemento asp:Content con el identificador PlaceHolderMain.
Agregue el marcado siguiente justo debajo del botón
purgeCompletedItems
.<p><asp:Button runat="server" OnClientClick="return ensureOrientationScheduling()" ID="ensureorientationschedulingbutton" Text="Ensure all items are on the Calendar" /></p>
Recopile el proyecto en Visual Studio.
Para minimizar la necesidad de establecer de forma manual la Fase de orientación de los elementos de la lista como No iniciada mientras se prueba el complemento, abra el archivo elements.xml de la instancia de lista NuevosEmpleadosDeSeattle (no el archivo elements.xml de la plantilla de lista NuevaOrientaciónEmpleados) y asegúrese de que el valor Fase de orientación de al menos tres de los elementos Row, incluida la fila de Claudia Olivares, tengan el valor No iniciada. Como este es el valor predeterminado, la forma más sencilla de hacerlo es asegurarse de que no haya ningún elemento Field para
OrientationStage
en las tres (o más) filas.El siguiente es un ejemplo del aspecto del elemento Rows.
<Rows> <Row> <Field Name="Title">Tom Higginbotham</Field> <Field Name="Division">Manufacturing</Field> <Field Name="OrientationStage">Completed</Field> </Row> <Row> <Field Name="Title">Satomi Hayakawa</Field> </Row> <Row> <Field Name="Title">Cassi Hicks</Field> </Row> <Row> <Field Name="Title">Lertchai Treetawatchaiwong</Field> </Row> </Rows>
Especificar los permisos de la web de host que necesita el complemento
El complemento automáticamente tiene permiso de control total en su propia web de complemento, por lo que hasta ahora no se necesita especificar los permisos que necesita. Pero debemos solicitar específicamente permisos a la web de host para interactuar con sus datos. El complemento Orientación del empleado necesita permiso para agregar elementos al calendario en la web de host.
En el Explorador de soluciones, abra el archivo appmanifest.xml.
En el diseñador de manifiestos, abra la ficha Permisos.
En la fila superior de la columna Ámbito, seleccione Lista en la lista desplegable.
En la columna Permiso, seleccione Administrar.
Si la columna Propiedades se deja en blanco, el complemento pide permiso de escritura en cada lista de la web de host. Una buena práctica pasa por limitar los complementos solamente a los permisos que necesitan. En el manifiesto del complemento no hay ninguna forma de limitar los permisos a una instancia de lista específica, pero se puede limitar el complemento para enumerar solamente las instancias que están integradas en una plantilla de lista base específica. La plantilla de lista base de un calendario es Eventos, cuyo id. numérico es 106.
Seleccione la celda Propiedades de la misma fila para que el botón Editar aparezca en la celda. La lista de permisos tendrá un aspecto similar al siguiente.
Figura 2. Lista de permisos con el botón Editar visible
Seleccione Editar para abrir el cuadro de diálogo Propiedades.
Defina el Nombre en BaseTemplateId y ajuste el Valor en 106. Ahora el cuadro de diálogo debería tener este aspecto.
Figura 3. Cuadro de diálogo de propiedades de permisos de lista
Seleccione Aceptar. Ahora la pestaña Permisos será similar a la siguiente.
Figura 4. Ficha Permisos de diseñador de manifiestos de complemento en Visual Studio
Ejecutar y probar el complemento
Asegúrese de que el calendario de web de host esté preparado tal como se ha descrito anteriormente en este artículo. Debe tener un solo evento, denominado Orientar a Claudia Olivares.
Habilite las ventanas emergentes en el explorador que Visual Studio usa durante la depuración.
Use la tecla F5 para implementar y ejecutar el complemento. Visual Studio realizará una instalación temporal del complemento en el sitio de SharePoint de prueba y ejecutará el complemento inmediatamente.
Se abrirá el formulario para conceder al complemento el permiso necesario. La página contiene una lista desplegable en la que puede elegir entre todos los calendarios de la web de host. Seleccione Programa de orientación para empleados y después seleccione Confiar.
Figura 5. Solicitud de consentimiento de complemento en SharePoint
Cuando la página de inicio del complemento se cargue por completo, seleccione el botón Comprobar que los elementos estén programados.
Figura 6. Página principal Orientación del empleado con botón nuevo
Si se ejecuta cualquiera de las funciones de devolución de llamada por error, verá la alerta de mensaje de error que crean las funciones de devolución de llamada. De lo contrario, verá el mensaje de operación correcta que creó la devolución de llamada confirmada final: Había una o más orientaciones no programadas y se agregaron al calendario Programa de orientación para empleados.
Vaya al calendario Programa de orientación para empleados en la web de host. Por ejemplo, seleccione el vínculo de la ruta de navegación a la página principal del sitio de desarrollo y seleccione Contenido del sitio. Seleccione el icono Programa de orientación para empleados (no el icono Orientación para empleados).
El calendario debe ser similar al siguiente. El script detectó que ya había un evento para Cassi Hicks, por lo que no creó un segundo evento para ella. Creó eventos para los otros dos empleados cuya orientación estaba en estado No iniciada. Tampoco creó un evento para el empleado cuya orientación era anterior al estado No iniciado.
Figura 7. Calendario después de agregar dos eventos nuevos
Asegúrese de eliminar los dos nuevos eventos del calendario antes de volver a seleccionar Comprobar que los elementos estén programados.
Para finalizar la sesión de depuración, cierre la ventana del explorador o detenga la depuración en Visual Studio. Cada vez que seleccione F5, Visual Studio retirará la versión anterior del complemento e instalará la más reciente.
Trabajará con este complemento y con la solución de Visual Studio en otros artículos. Es recomendable que vuelva a retirar el complemento cuando deje de trabajar con él por un tiempo. Haga clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccione Retirar.
Pasos siguientes
Realice trabajo avanzado en complementos de SharePoint hospedados en SharePoint: