javascript - Meteor: Página de perfil de usuario con Iron Router
iron-router (1)
Estoy luchando para crear una página de perfil de usuario, utilizando Iron Router, que se encuentra en localhost:3000/:username
. La página de perfil debe tener las siguientes características:
- Vista pública: cualquiera puede ver información básica sobre el usuario
- Vista privada: si el cliente visita su propia página de perfil mientras está conectado, se muestran sus datos de usuario confidenciales y tienen capacidades de edición.
- Vista de carga: mientras se recuperan los datos del perfil de usuario, muestra una pantalla de carga
- Vista no encontrada: si se ingresa un nombre de usuario no válido en la URL, devuelve una página no encontrada.
La vista pública y la vista privada deberían existir en la misma ruta de URL. Dependiendo de las credenciales del cliente, ven uno u otro sin una redirección a una página diferente. La página no encontrada tampoco debería redirigir, de esta manera el usuario aún puede ver la URL no válida en la barra de la URL del navegador si ingresa un nombre de usuario no válido.
Mi archivo router.js:
this.route(''profile'', {
controller: ''ProfileController'',
path: ''/:username''
});
Dentro de ProfileController
, estoy tratando de reunir lo siguiente:
-
onBeforeAction
- muestra la pantalla de carga; determinar si existe un nombre de usuario (también conocido como si la URL es válida)- Mostrar vista no encontrada, perfil privado o perfil público
-
waitOn
- espera a que se recuperen los datos delusername
deusername
antes de quitar la pantalla de carga -
onAfterAction
- eliminar la pantalla de carga
¡Gracias!
Afortunadamente, todas las características que estás buscando están disponibles como complementos horneados, por lo que ni siquiera tendrás que sumergirte en la definición de tus propios ganchos.
Tenga en cuenta que estoy usando iron:[email protected]
, esto es importante para mantenerse al día con las últimas novedades, solo hay dos caprichos menores en este momento que espero que se solucionen pronto.
Comencemos con la publicación del perfil de usuario, que toma el nombre de usuario como argumento.
server/collections/users.js
Meteor.publish("userProfile",function(username){
// simulate network latency by sleeping 2s
Meteor._sleepForMs(2000);
// try to find the user by username
var user=Meteor.users.findOne({
username:username
});
// if we can''t find it, mark the subscription as ready and quit
if(!user){
this.ready();
return;
}
// if the user we want to display the profile is the currently logged in user...
if(this.userId==user._id){
// then we return the corresponding full document via a cursor
return Meteor.users.find(this.userId);
}
else{
// if we are viewing only the public part, strip the "profile"
// property from the fetched document, you might want to
// set only a nested property of the profile as private
// instead of the whole property
return Meteor.users.find(user._id,{
fields:{
"profile":0
}
});
}
});
Continuemos con la plantilla de perfil, aquí no hay nada demasiado sofisticado, mostraremos el nombre de usuario como datos públicos y, si estamos viendo el perfil privado, mostraremos el nombre real del usuario que suponemos que está almacenado en profile.name
.
client/views/profile/profile.html
<template name="profile">
Username: {{username}}<br>
{{! with acts as an if : the following part won''t be displayed
if the user document has no profile property}}
{{#with profile}}
Profile name : {{name}}
{{/with}}
</template>
Entonces tenemos que definir una ruta para la vista de perfil en la configuración del enrutador global:
lib/router.js
// define the (usually global) loading template
Router.configure({
loadingTemplate:"loading"
});
// add the dataNotFound plugin, which is responsible for
// rendering the dataNotFound template if your RouteController
// data function returns a falsy value
Router.plugin("dataNotFound",{
notFoundTemplate: "dataNotFound"
});
Router.route("/profile/:username",{
name:"profile",
controller:"ProfileController"
});
Tenga en cuenta que iron:router
ahora requiere que defina sus rutas y controladores de ruta en el directorio compartido (generalmente este es el lib/
dir en la raíz de su proyecto) disponible tanto para el cliente como para el servidor.
Ahora, para la parte más difícil, la definición ProfileController
:
lib/controllers/profile.js
ProfileController=RouteController.extend({
template:"profile",
waitOn:function(){
return Meteor.subscribe("userProfile",this.params.username);
},
data:function(){
var username=Router.current().params.username;
return Meteor.users.findOne({
username:username
});
}
});
Cuando iron:router
detecta que está usando waitOn
en un RouteController
, ahora agregará automáticamente el hook de loading
predeterminado que es responsable de procesar el loadingTemplate
mientras la suscripción aún no está lista.
Me referiré ahora a los dos errores menores de los que he hablado al principio de mi respuesta.
Primero, la guía oficial de iron:router
(que definitivamente debería leer) http://eventedmind.github.io/iron-router/ menciona que el nombre de la opción que debe pasar al plugin dataNotFoundTemplate
es dataNotFoundTemplate
pero a partir de 28- 09-2014 esto no funcionará, necesita usar el nombre heredado notFoundTemplate
, esto probablemente se solucione en cuestión de días.
Lo mismo aplica para el código de mi función de data
en el controlador: he utilizado la sintaxis contra-intuitiva Router.current().params
para acceder a los parámetros de ruta cuando normalmente this.params
habría sido la sintaxis regular apropiada. Este es otro problema que aún no se ha abordado. https://github.com/EventedMind/iron-router/issues/857