简体   繁体   中英

keystone.js : how can I display content from 2 different models on my index page

I am working with keystone.js on a Project. And I am doing Templating with Handlebars(hbs) What I want to do: On my index page I want to display a slider(solved this with unslider.js so I only need to be able to display the images and text from slider model) and the 3 newest events(That works). Here is my code so far:

This is my Event Model

var keystone = require('keystone');
var Types = keystone.Field.Types;

/**
 * Event Model
 * ==========
 */

var Event = new keystone.List('Event', {
    map: { name: 'title' },
    autokey: { path: 'slug', from: 'title', unique: true },
});

Event.add({
    title: { type: String, required: true },
    state: { type: Types.Select, options: 'draft, published, archived', default: 'draft', index: true },
    author: { type: Types.Relationship, ref: 'User', index: true },
    publishedDate: { type: Types.Date, index: true, dependsOn: { state: 'published' } },
    image: { type: Types.CloudinaryImage },
    content: {
        brief: { type: Types.Html, wysiwyg: true, height: 150 },
        extended: { type: Types.Html, wysiwyg: true, height: 400 },
    },
    eventcategories: { type: Types.Relationship, ref: 'EventCategory', many: true },
});

Event.schema.virtual('content.full').get(function () {
    return this.content.extended || this.content.brief;
});

Event.defaultColumns = 'title, state|20%, author|20%, publishedDate|20%';
Event.register();

And this my slider Model

var keystone = require('keystone');
var Types = keystone.Field.Types;

/**
 * slider Model
 * ==========
 */

var Slider = new keystone.List('Slider', {
    map: { name: 'title' },
    autokey: { path: 'slug', from: 'title', unique: true },
});

Slider.add({
    title: { type: String, required: true },
    image: { type: Types.CloudinaryImage },
});

Slider.register();

Both models work correctly in the backend and it should only be a problem in the view... so here come index view

var keystone = require('keystone');

exports = module.exports = function (req, res) {

    var view = new keystone.View(req, res);


    var locals = res.locals;

    // Init locals
    locals.section = 'eventblog';
    locals.filters = {
        eventcategory: req.params.category,
    };


    // Set locals
    locals.section = 'slider';
    locals.data = {
        titles: [],  //maybe this is a problem?
        images: [],  //maybe this is a problem?
        events: [],
        eventcategories: [],
    }


    // locals.section is used to set the currently selected
    // item in the header navigation.
    locals.section = 'home';

    view.on('init', function (next) {

        var q = keystone.list('Event').paginate({
            page: req.query.page || 1,
            perPage: 3,
            maxPages: 1,
            filters: {
                state: 'published',
            },
        })
            .sort('-publishedDate')
            .populate('author categories');

        if (locals.data.eventcategory) {
            q.where('categories').in([locals.data.eventcategory]);
        }


        q.exec(function (err, results) {
            locals.data.events = results;
            next(err);
        });

    });










    // Render the view
    view.render('index');
};

And here is my index.hbs

<div class="container">


    <div class="my-slider">
        <ul>

            {{#each slider}}
                <!-- doesn't loop even once-->

                                <li>
                                    <img src="{{cloudinaryUrl image width='300' height='300'}}" >
                                    <p>{{title}}</p>
                                </li>

            {{/each}}

        </ul>
    </div>
    <!-- the code below works correctly -->
    <div class="events row">

        {{# each data.events.results}}
            <div class="col-md-4 col-lg-4">
                <h3><a href="{{eventUrl slug}}">{{{title}}}</a></h3>
                <p class=" text-muted">{{{categoryList categories prefix="Posted in "}}}
                    {{#if author.name.first}}by {{author.name.first}}{{/if}}
                </p>
                {{#if image}}<img src="{{{cloudinaryUrl image  height=160 crop='fit' }}}" class="img center-block">{{/if}}
                <p>{{{content.brief}}}</p>
                {{#if content.extended}}<p class="read-more"><a href="{{eventUrl slug}}">Read more...</a></p>{{/if}}
            </div>
        {{/each}}
    </div>
</div>

I really hope that my question is clear and someone can help me

The code in your route sets locals.data.events which is why you can use it from handlebars. However, you're not setting locals.slider which is why that {{#each slider}} loop doesn't execute.

In your route, you also need to do something like

keystone.list('Slider').model.find().exec(function (err, results) {
    locals.sliders = restuls;
    next(err);
}

which populates locals.slider so that in you can do {{#each slider}} in your hbs template. The rest of your code should then work fine.

(Disclaimer, I've not actually tested this, but it should work. If not, try and work out what happened. There are plenty of examples of this kind of code in the keystone demo project )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM