Add a way to dynamically set a hidden field's value #82

Closed
d4goxn opened this Issue Oct 23, 2013 · 11 comments

3 participants

@d4goxn

Is it possible to set the value of a widget? I tried several variations on the following:

forms.create({
    _csrf: forms.widgets.hidden({ value: 'a csrf token' })
}).toHTML()

I assume that I'm doing it wrong, so I asked a question on SO showing my other attempts. @ljharb mentioned in #70 that this should be simple, but I'm not feeling too bright right now. I tried using fields.string({ type: hidden, value: 'a csrf token' }), but that's not right either.

@ljharb
Collaborator
forms.create({
    csrf: forms.widgets.hidden({
        required: true,
        validators: [
            function (form, field, callback) {
                if (form.fields.csrf !== getExpectedCSRFTokenValue()) {
                    callback('bad csrf token');
                } else {
                    callback();
                }
            }
        ]
    })
}).bind({ csrf: 'a token' });

? I haven't tried this yet, but something like that should work?

@ljharb
Collaborator

If you get a working solution, I think I've changed my mind - a generic "must match value" widget, that takes a "getValue" function and an "initialValue", might serve your purposes quite well.

@d4goxn

This is just weird:

> var form = forms.create({ csrf: forms.widgets.hidden() });
> form.bind({ csrf: 'token' });

Throws an error, TypeError: Object #<Object> has no method 'bind', but form certainly does have a bind method:

> form.bind
[Function]

This is with 0.3.0, installed using npm. I would like to clone the repo and start poking around, but right now I have a late project and so I think I should just to do the hidden input manually in the templates for now. Thank you for all your work on this much needed module, I hope I can sort this out after I catch up to my deadline.

@ljharb
Collaborator

Sounds good, I'd love to make forms more useful. I think the argument to form.bind might need to be different - maybe { fields: { csrf: 'token' } }? i'll take a look at the code later

@ljharb ljharb self-assigned this Feb 26, 2014
@ljharb ljharb added a commit that referenced this issue Mar 12, 2014
@ljharb ljharb Adding a matchValue validator.
Relates to #82.
6e94910
@ljharb
Collaborator

I've added a matchValue validator that takes a getter function.

@ljharb ljharb closed this Jul 5, 2014
@elantion

My situation is quite similar to d4goxn. And I just need to have a value attribute with the csrfToken in it.But wired, I try this:

    var loginForm = forms.create({
         username: fields.string({ required: validators.required('xxxx') }),
         password: fields.password({ required: validators.required('xxxx') }),
        csrfToken: widgets.hidden({
            required: true
        })
    }).bind({ fields:{ csrfToken: req.csrfToken() }});

"no bind function error"

and this:

    var loginForm = forms.create({
         username: fields.string({ required: validators.required('xxxx') }),
         password: fields.password({ required: validators.required('xxxx') }),
        csrfToken: widgets.hidden({
            required: true
                 value: req.csrfToken()
        })
    });

I dump the csrf value, it's there. But at the end, the form didn't have a value attribute.

And I try 'value':req.csrfToken() too.
it dosen't work too.

pls help, thnks.

@ljharb
Collaborator

@elantion In your second snippet you're missing a comma - is that just a copy/paste error, or is that in your original code?

As for "no bind function error" can you gist the actual output you're getting?

@elantion

Thanks your reply.
The second snippet syntax error just a copy/paste mistake. The code is find.
'no bind function error' detail :

TypeError: undefined is not a function
   at /Users/jamesying/Desktop/lc/node_modules/forms/lib/forms.js:36:47 
   at Array.forEach (native)
   at Object.f.bind (/Users/jamesying/Desktop/lc/node_modules/forms/lib/forms.js:34:35)
   at /Users/jamesying/Desktop/lc/routes/articles.js:25:8
   at Layer.handle [as handle_request] (/Users/jamesying/Desktop/lc/node_modules/express/lib/router/layer.js:82:5)
   at next (/Users/jamesying/Desktop/lc/node_modules/express/lib/router/route.js:110:13)
   at csrf (/Users/jamesying/Desktop/lc/node_modules/csurf/index.js:97:5)
   at Layer.handle [as handle_request] (/Users/jamesying/Desktop/lc/node_modules/express/lib/router/layer.js:82:5)
   at next (/Users/jamesying/Desktop/lc/node_modules/express/lib/router/route.js:110:13)
   at Route.dispatch (/Users/jamesying/Desktop/lc/node_modules/express/lib/router/route.js:91:3)
@elantion

Yes, I am making another form. But I use the same way to create the form.

/* add article */
router.get('/add', csrfProtection, function(req, res) {
    var add_form = forms.create({
        title: fields.string({ required: true }),
        content: fields.string({ required: validators.required('请输入内容') }),
        csrfToken:forms.widgets.hidden({required:true})
    }).bind({ fields:{ csrfToken: req.csrfToken() }});
    add_form.toHTML();
    res.render('article/add',{
        add_form:add_form
    });
});
@ljharb
Collaborator

@elantion This discussion should really go in a brand new issue. Can you file one?

@elantion

sure, I will do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment