1

My task is to upload an image and update the user table without the page being refreshed. My search suggested to grab the form elements with refs but I'm getting, in console:

ActionController::ParameterMissing (param is missing or the value is empty: user):

app/controllers/users_controller.rb:8:in user_params' app/controllers/users_controller.rb:3:inupdate'

Routes:

Rails.application.routes.draw do
  get 'welcome/index'

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root 'welcome#index'
  resources :users do
    member do
      post 'upload' => 'users#update'
    end
  end
end

The app:

var User = React.createClass({

  componentDidMount: function(){
    // Trying so see what this shows in the browser console
    var foo = $(this.refs.myForm).elements;
    console.log(foo);
  }.bind(this),

  onUpload: function(){
    var formData = $(this.refs.myForm).serialize();
    $.ajax({
       url: '/users/1/upload',
       type: 'POST',
       data: formData,
       async: false,
       cache: false,
       contentType: false,
       processData: false,
       success: function (data) {
           console.log("success: " + data);
       },
       error: function () {
           alert("error in ajax form submission");
       }
    });
  },
  render: function(){
    return(
      <div>
        <form ref="myForm" remote="true">
          <input type="file" name="user[avatar]" />
        </form>
         {/* Placing the button outside the form prevents a refresh */}
        <button className="button" onClick={this.onUpload}>Upload</button>
      </div>
    )
  }
});
module.exports = User;

User Controller:

class UsersController < ApplicationController
  def update
    User.find(1).update_attributes(user_params)
  end

  private
    def user_params
      params.require(:user).permit(:avatar)
    end
end

I've see that, on the web, other people used this.refs.myForm.elements so what's wrong here?

Sylar
  • 11,422
  • 25
  • 93
  • 166

2 Answers2

0

change

<input type="file" name="user[avatar]" />

to

<input type="file" name="user" />

remove bind(this) from componentDidMount

change

  componentDidMount: function(){
    // Trying so see what this shows in the browser console
    var foo = $(this.refs.myForm).elements;
    console.log(foo);
  }.bind(this),

to

componentDidMount: function(){
    // Trying so see what this shows in the browser console
    var foo = $(this.refs.myForm).elements;
    console.log(foo);
  },
Piyush.kapoor
  • 6,715
  • 1
  • 21
  • 21
  • No. It must be like this: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html My `ref` is undefined anywhere I place it. – Sylar Jun 26 '16 at 07:09
  • can u check what the value of $(this.refs.myForm).serialize(); in the console . – Piyush.kapoor Jun 26 '16 at 07:11
  • Uncaught TypeError: Cannot read property 'myForm' of undefined – Sylar Jun 26 '16 at 07:12
  • strange this.refs should contain myForm – Piyush.kapoor Jun 26 '16 at 07:13
  • I know. Placing a ref on the button is the same. This is just a new rails 5 app with nothing else. `rails _5.0.0.rc1_ new demo --database=postgresql` – Sylar Jun 26 '16 at 07:15
  • remove bind(this) componentDidMount , you should not bind componentDidMount , that why this was undefined in componentDidMount – Piyush.kapoor Jun 26 '16 at 07:22
  • That function was to mess with. Deleting it makes no difference. – Sylar Jun 26 '16 at 07:23
  • if your bind this then babel transpiler is messing up this , making it undefined checked in codepen – Piyush.kapoor Jun 26 '16 at 07:26
  • Oh! It's removed and in browser console it's showing blank: nothing. Just a white space. In the render it's showing as `undefined` – Sylar Jun 26 '16 at 07:28
  • $(this.refs.myForm) isnt jquery element now – Piyush.kapoor Jun 26 '16 at 07:33
  • Lets sort this first: my ref is not working at all. Ive adding an input field with `ref="test"` and `this.refs.test` shows blank in the console. Weird. – Sylar Jun 26 '16 at 07:36
  • for input files jquery serialize I have checked . this.refs.test should work have used it 1000 times console.log(this.refs) I used your code in codepen I am seeing the refs – Piyush.kapoor Jun 26 '16 at 07:44
  • Weird. Other project `refs` work. See my full code: https://github.com/SylarRuby/react_ajax_upload – Sylar Jun 26 '16 at 08:04
  • Ok. Updated to react 15.1.0 and refs now works. What's the correct way for: `$(this.refs.myForm).serialize();`? – Sylar Jun 26 '16 at 09:06
  • this is the correct way. but it wont give you input file .For the file stuff follow this link http://stackoverflow.com/questions/5392344/sending-multipart-formdata-with-jquery-ajax – Piyush.kapoor Jun 26 '16 at 09:10
  • `var foo = $(this.refs.myForm).elements;` is undefined. `var foo = $(this.refs.myForm).context;` gives me the html-like syntax in the console. How to serialize that so rails sees the params? – Sylar Jun 26 '16 at 09:25
0

Ok. Thanks for your help, Piyush, for your time and effort. You have given me clues of what to search for. Moh Arjmandi has the answer here.

To rewire my function:

onUpload: function(){
    var fd = $(this.refs.myForm).context;
    var formData = new FormData(fd);
    $.ajax({
       url: '/users/1/upload',
       type: 'POST',
       data: formData,
       async: false,
       cache: false,
       contentType: false,
       processData: false,
       success: function (data) {
           console.log("success: " + data);
       },
       error: function () {
           alert("error in ajax form submission");
       }
    });
  },

Quoted by Moh:

serialize() is not a good idea if you want to send a form with post method. For example if you want to pass a file via ajax its not gonna work.

And the complete app here.

Community
  • 1
  • 1
Sylar
  • 11,422
  • 25
  • 93
  • 166