Ad

Uploading LocalFile In Keystone.js Using UpdateHandler

How might one go about doing this? Here, someone suggests using an UpdateHandler or an underscore method of the list item as in profileImage._.uploadImage(file, update, callback) to handle the file upload, but they use an S3 File instead of a LocalFile. I tried using an underscore method first but it doesn't seem to work as it does in the above question. There's a lot of scattered documentation on other sites but it all appears to be outdated (some suggest using methods of the LocalFile that don't exist anymore, for example) and contains many broken links.

View js (middleware) code:

view.on('post', { action: 'edit-profile' }, next => {       
    let updater = locals.user.getUpdateHandler(req, res, {
        errorMessage: 'There was an error editing your profile:'
    });

    updater.process(req.body, {
        flashErrors: true,
        logErrors: true,
        fields: 'profileImage, email, name, password'
    }, err => {
        if (err) {
            locals.validationErrors = err.errors;
            next();
        } else {
            req.flash('success', 'Profile updated');
            res.redirect('/profile');
        }
    });
});

Jade code:

mixin edit-profile()
form(method='post', enctype='multipart/form-data', autocomplete='off', novalidate).form-horizontal.create-form.profile-form
    input(type='hidden', name='action', value='edit-profile')

    .row: .col-sm-8.col-sm-offset-2

        h2 Edit Profile

        .form-group
            +user-picture(locals.user)
            label(for="profileImage") Change profile picture
            input(type='file', id='profileImage' name='profileImage')
        .form-group
            label(for="email") Email
            input(type='email', value=locals.user.email, size="40", id='email', name='email', placeholder='email').input.input-xl.input-faded
        .form-group
            label(for="email") Name
            input(type='text', value=locals.user.name.first, name='name.first', placeholder='First name').input.input-xl.input-faded
            input(type='text', value=locals.user.name.last, name='name.last', placeholder='Last name').input.input-xl.input-faded
        .form-group
            label(for="password") Change password
            input(type='password', id="password", name='password', placeholder='password').input.input-xl.input-faded
            input(type='password', name='password_confirm', placeholder='password').input.input-xl.input-faded
        .form-group
            button(type='submit', data-loading-text="Changing...").btn.btn-lg.btn-primary.btn-block Update profile
Ad

Answer

It turns out the issue is that Keystone.js is very picky about what the input field is named when it comes to LocalFile uploads. It isn't documented anywhere on Keystone's website (in fact, nothing about UpdateHandler is it seems), but you need to put _upload after the name.

So, the Jade code should look like this (notice the difference in the first .form-group):

mixin edit-profile()
form(method='post', enctype='multipart/form-data', autocomplete='off', novalidate).form-horizontal.create-form.profile-form
input(type='hidden', name='action', value='edit-profile')

.row: .col-sm-8.col-sm-offset-2

    h2 Edit Profile

    .form-group
        +user-picture(locals.user)
        label(for="profileImage_upload") Change profile picture
        input(type='file', id='profileImage_upload' name='profileImage_upload')
    .form-group
        label(for="email") Email
        input(type='email', value=locals.user.email, size="40", id='email', name='email', placeholder='email').input.input-xl.input-faded
    .form-group
        label(for="email") Name
        input(type='text', value=locals.user.name.first, name='name.first', placeholder='First name').input.input-xl.input-faded
        input(type='text', value=locals.user.name.last, name='name.last', placeholder='Last name').input.input-xl.input-faded
    .form-group
        label(for="password") Change password
        input(type='password', id="password", name='password', placeholder='password').input.input-xl.input-faded
        input(type='password', name='password_confirm', placeholder='password').input.input-xl.input-faded
    .form-group
        button(type='submit', data-loading-text="Changing...").btn.btn-lg.btn-primary.btn-block Update profile

If you're using standard HTML, it's no different really. Just set the id and name of the input to be fieldnamehere_upload (in my case, the LocalFile's field name is profileImage). The updater code is accurate as is (be careful, the order of the fields in the argument to updater.process should be the same as the order of the input fields in your form).

I wouldn't recommend using the underscore method the list has. It seems harder than using the UpdateHandler as shown here.

Ad
source: stackoverflow.com
Ad