Meteor: หน้าโปรไฟล์ผู้ใช้พร้อม Iron Router

ฉันกำลังประสบปัญหาในการสร้างหน้าโปรไฟล์ผู้ใช้โดยใช้ Iron Router ซึ่งอยู่ที่ localhost:3000/:username หน้าโปรไฟล์ควรมีลักษณะดังต่อไปนี้:

  • มุมมองสาธารณะ - ทุกคนสามารถดูข้อมูลพื้นฐานเกี่ยวกับผู้ใช้ได้
  • มุมมองส่วนตัว - หากลูกค้าเยี่ยมชมหน้าโปรไฟล์ของตนเองในขณะที่ลงชื่อเข้าใช้ ข้อมูลผู้ใช้ที่ละเอียดอ่อนของเขาหรือเธอจะแสดงขึ้นและพวกเขาจะมีความสามารถในการแก้ไข
  • กำลังโหลดมุมมอง - ขณะที่กำลังดึงข้อมูลโปรไฟล์ผู้ใช้ ให้แสดงหน้าจอการโหลด
  • ไม่พบมุมมอง - หากป้อนชื่อผู้ใช้ที่ไม่ถูกต้องใน URL ให้ส่งคืนหน้าที่ไม่พบ

มุมมองสาธารณะและมุมมองส่วนตัวควรมีอยู่ในเส้นทาง URL เดียวกัน พวกเขาจะเห็นอย่างใดอย่างหนึ่งโดยไม่มีการเปลี่ยนเส้นทางไปยังหน้าอื่น ทั้งนี้ขึ้นอยู่กับข้อมูลประจำตัวของลูกค้า หน้าที่ไม่พบไม่ควรเปลี่ยนเส้นทาง ด้วยวิธีนี้ผู้ใช้จะยังคงเห็น URL ที่ไม่ถูกต้องในแถบ URL ของเบราว์เซอร์หากป้อนชื่อผู้ใช้ที่ไม่ถูกต้อง

ไฟล์ router.js ของฉัน:

this.route('profile', {
    controller: 'ProfileController',
    path: '/:username'
  });

ภายใน ProfileController ฉันกำลังพยายามรวบรวมสิ่งต่อไปนี้:

  • onBeforeAction - show loading screen; determine if username exists (aka if URL is valid)
    • Either show not found view, private profile, or public profile
  • waitOn - รอให้ดึงข้อมูลของ username ก่อนที่จะลบหน้าจอการโหลด
  • onAfterAction - ลบหน้าจอการโหลด

ขอบคุณ!


person Jon Cursi    schedule 28.09.2014    source แหล่งที่มา


คำตอบ (1)


โชคดีที่ทุกคุณลักษณะที่คุณกำลังมองหานั้นมีอยู่ในปลั๊กอิน ดังนั้นคุณจึงไม่จำเป็นต้องเจาะลึกในการกำหนด hooks ของคุณเองด้วยซ้ำ

โปรดสังเกตว่าฉันใช้ iron:[email protected] ซึ่งเป็นสิ่งสำคัญในการติดตามข่าวสารล่าสุด มีเพียงสองประเด็นเล็กๆ น้อยๆ ในขณะนี้ที่ฉันหวังว่าจะได้รับการแก้ไขในเร็วๆ นี้

เริ่มต้นด้วยการเผยแพร่โปรไฟล์ผู้ใช้ ซึ่งใช้ชื่อผู้ใช้เป็นอาร์กิวเมนต์

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
            }
        });
    }
});

มาดูเทมเพลตโปรไฟล์กันต่อ ไม่มีอะไรพิเศษเกินไปที่นี่ เราจะแสดงชื่อผู้ใช้เป็นข้อมูลสาธารณะ และหากเรากำลังดูโปรไฟล์ส่วนตัว ก็แสดงชื่อจริงของผู้ใช้ที่เราถือว่าถูกเก็บไว้ใน 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>

จากนั้นเราจำเป็นต้องกำหนดเส้นทางสำหรับมุมมองโปรไฟล์ในการกำหนดค่าเราเตอร์ทั่วโลก:

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"
});

โปรดทราบว่าตอนนี้ iron:router ต้องการให้คุณกำหนดเส้นทางและตัวควบคุมเส้นทางของคุณในไดเร็กทอรีที่ใช้ร่วมกัน (โดยปกติคือ lib/ dir ที่รากของโปรเจ็กต์ของคุณ) ที่พร้อมใช้งานสำหรับทั้งไคลเอ็นต์และเซิร์ฟเวอร์

ตอนนี้สำหรับส่วนที่ยากที่สุด 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
        });
    }
});

เมื่อ iron:router ตรวจพบว่าคุณกำลังใช้ waitOn ใน RouteController ตอนนี้จะเพิ่มตะขอ loading เริ่มต้นโดยอัตโนมัติ ซึ่งมีหน้าที่รับผิดชอบในการแสดงผล loadingTemplate ในขณะที่การสมัครสมาชิกยังไม่พร้อม

ตอนนี้ฉันจะพูดถึงข้อบกพร่องเล็กๆ น้อยๆ สองข้อที่ฉันได้พูดถึงไปแล้วในการเริ่มคำตอบ

ก่อนอื่น iron:router คำแนะนำอย่างเป็นทางการ (ซึ่งคุณควรอ่านอย่างแน่นอน) http://eventedmind.github.io/iron-router/ ระบุว่าชื่อของตัวเลือกที่คุณควรส่งไปยังปลั๊กอิน dataNotFound คือ dataNotFoundTemplate แต่ ณ วันที่ 28-09-2557 สิ่งนี้จะไม่ทำงาน คุณต้องใช้ชื่อเดิม notFoundTemplate ซึ่งมีแนวโน้มที่จะได้รับการแก้ไขในเรื่องหนึ่ง ของวัน

เช่นเดียวกับโค้ดของฟังก์ชัน data ของฉันในคอนโทรลเลอร์: ฉันใช้ไวยากรณ์ที่เคาน์เตอร์ใช้งานง่าย Router.current().params เพื่อเข้าถึงพารามิเตอร์เส้นทางเมื่อปกติ this.params จะเป็นไวยากรณ์ปกติที่เหมาะสม นี่เป็นอีกปัญหาที่ยังได้รับการแก้ไข https://github.com/EventedMind/iron-router/issues/857

person saimeunt    schedule 28.09.2014
comment
ขอบคุณมากสำหรับความช่วยเหลือของคุณ! ฟังก์ชัน Meteor.publish() นั้นใช้งานได้ดีสำหรับการเผยแพร่ข้อมูลเฉพาะเกี่ยวกับผู้ใช้ที่เป็นปัญหาเท่านั้น - person Jon Cursi; 29.09.2014
comment
นี่เป็นการเขียนที่ดีขอบคุณ น่าสังเกตสำหรับผู้อ่านในอนาคต รหัสนี้ใช้ไม่ได้กับ audit-argument-checks ติดตั้งแพ็คเกจแล้ว - person AlecRust; 27.10.2015
comment
หากคุณมีเทมเพลตหน้าโปรไฟล์ คุณจะรับค่าฟิลด์ของผู้ใช้ของหน้าโปรไฟล์เฉพาะนั้นทางฝั่ง js ได้อย่างไร - person Barry Michael Doyle; 04.02.2016