I am trying to submit form in react js with Rails.
I am new to React js and it is my first app
I am getting error No route matches [POST] "/"
Using single component(jsx) to submit the form.I am getting routing error.
Following is my code
EDIT
I changed the route and now I got error "InvalidAuthenticityToken in ItemsController#create"
How can i raise or alert variable in in jsx file ?
I add following route in route.rb
resources :items
root :to => redirect("/items")
ItemsController
def index
#presenter = { :action => items_path,
:csrf_token => request_forgery_protection_token,
:csrf_param => form_authenticity_token
}
end
def create
#item = Item.new(item_params)
#item.save
end
private
def item_params
params.require(:item).permit(:name, :price)
end
Index.html.erb
<%= react_component('Form1', {:presenter => #presenter.to_json}, {:presenter => true})%>
Form1.js.jsx
var Form1 = React.createClass({
handeSubmit: function( e ){
e.preventDefault();
// var form = e.target;
// var name = form.querySelector('[name="item[name]"]').value;
// var price = form.queySelector('[name="item[price]"]').value;
var name = this.refs.name.getDOMNode().value.trim();
var price = this.refs.price.getDOMNode().value.trim();
if(!name || !price)
{
return false;
}
var formData = $( this.refs.form.getDOMNode() ).serialize();
var action = this.props.presenter.action
// alert({formData});
$.ajax({
data: formData,
url: action,
type: "POST",
dataType: "json",
});
},
render: function(){
return (
<form ref="form" className="" action={ this.props.presenter.action } acceptCharset="UTF-8" method="post" onSubmit={this.handleSubmit} >
<input type="hidden" name={ this.props.presenter.csrf_param } value={ this.props.presenter.csrf_token } />
<input ref="name" name="item[name]" /><br/>
<input ref="price" name="item[price]" /><br/>
<button type="submit"> Submit</button>
</form>
)
}
});
It looks like, for AJAX requests, you should send the CSRF token as a header, not as a form field.
(Docs: http://api.rubyonrails.org/classes/ActionView/Helpers/CsrfHelper.html#method-i-csrf_meta_tags)
Here's how you could add that header in your case:
var csrfToken = this.props.presenter.csrf_token;
$.ajax({
data: formData,
url: action,
type: "POST",
dataType: "json",
// Before sending, add the CSRF header:
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
},
});
Does that work for you?
By the way, one way I work around this is by using react_component for form fields, but using Rails' form_for to make the actual <form> tag. For example,
<%= form_for #item, remote: true do |f| %>
<!-- Rails will add CSRF token -->
<%= react_component("ItemFormFields", item: #item) %>
<% end %>
Related
Ajax call to call POST of a model return 404 error
Not sure why there are 2 post calls made.
Is the route the issue?
show.html.erb:
<script type="text/javascript">
var apiKey = '<%= #api_key %>';
var sessionId = '<%= #room.session_id %>';
var token = '<%= #token %>';
var room = '<%= #room %>';
</script>
<%= debug #room %>
<input type="hidden" name="_method" value="put" />
<script>
var session;
var connection_id;
var connectionCount;
initializeSession();
// Connect to the session
session.connect(token, function(error) {
// If the connection is successful, publish to the session
console.log("session connected")
if (error) {
handleError(error);
} else {
session.publish(publisher, handleError);
}
});
session.on("connectionCreated", function(event) {
console.log("connectionCreated");
console.log(room.id);
connectionCount++;
// jqueryFunction("Call from js to jquery");
$.ajax({
type: "PUT",
data: JSON.stringify({ room: {name: 'New_room'}, _method:'put' }),
url: "/rooms/" + room.id + "/connected",
contentType: 'application/json'
}).done(function( msg )
{
alert( "Data Saved: " + msg );
});
}
</script>
room GET /rooms/:id(.:format) rooms#show
PATCH /rooms/:id(.:format) rooms#update
PUT /rooms/:id(.:format) rooms#update
DELETE /rooms/:id(.:format) rooms#destroy
def update
# #room.update_attributes(params[:name])
end
Error:
POST http://localhost:3000/room/6 404 (Not Found)
POST http://localhost:3000/rooms/room 404 (Not Found)
Rails generate put request by inject the hidden field in the form with name of _method and the value put, like this
<input type="hidden" name="_method" value="put" />
so you need to change to this
$.ajax({
type: "POST",
dataType: "script",
url: '/rooms/5',
contentType: 'application/json',
data: {rooms:{name: "New_room"}, _method: "put"}
}).done(function( msg ) {
alert( "Data Saved: " + msg );
});
});
I have toggle button on my form and on toggling it i am sending ajax call request to save updated boolean value in the database from controller.
but it is sending Html and json request both. I just want to send only one json request. (using rails 3.*)
post_as_premium.html.erb
<%= form_for #editor, url: set_as_premium_reporter_path, remote: true do |f| %>
<div class="editorSettings">
<div class="premiumCheck">
<label class="clearfix" for="user_post_premium_permission">
<span class="checkBoxWrap <%= #editor.post_premium_permission ? 'allChecked' : '' %>">
<%= f.check_box :post_premium_permission %>
</span>
</label>
</div>
</div>
<% end %>
<script type="text/javascript">
if($("#user_post_premium_permission").parent("span").hasClass('allChecked')){
$("#user_post_premium_permission").attr('checked', true);
}else{
$("#user_post_premium_permission").attr('checked', false);
}
$("#user_post_premium_permission").on("change", function(){
if ($(this).prop('checked')){
$(this).parent("span").addClass("allChecked");
}else{
$(this).parent("span").removeClass("allChecked");
}
this.form.submit();
});
</script>
2 ] Controller -
def post_as_premium
#editor = current_user
end
def set_as_premium
if params[:editor] && params[:user][:post_premium_permission]
current_user.update_attributes(post_premium_permission: params[:user][:post_premium_permission])
respond_to do |format|
format.js { head :ok }
format.html { redirect_to post_as_premium_path(current_user)}
end
end
Instead of submitting the form with form.submit() you could make an AJAX POST request with $.post
$("#user_post_premium_permission").on("change", function(){
if ($(this).prop('checked')){
$(this).parent("span").addClass("allChecked");
} else {
$(this).parent("span").removeClass("allChecked");
}
// AJAX POST request
var url = $(this).parent("form").attr('action')
$.post(url, { editor: { post_premium_permission: $(this).prop('checked') } })
});
I want to send some data from view to controller in rails through ajax.
I have the following code in
app/view/static/home.html.erb
<script type="text/javascript">
var dummy = "testtext";
$('#finish').click(function() {
$.ajax( {
url: '/finish',
type: 'POST',
data: dummy,
dataType: 'text'
});
});
</script>
<body>
<%= button_to "Finish", {:action => 'finish', :controller => 'static'}, :method => :post, id => 'finish' %>
</body>
in
app/view/static/finish.html.erb
<p><%= #data %></p>
app/controller/static_controller.rb
def finish
#data = params[:data]
end
in routes.rb
post 'finish' => 'static#finish'
My understanding is that on button click the ajax script will be executed and rails action will store the data passed from view. This doesn't seem to work. I'm not sure if my understanding of the flow is right.
Because you are calling params[:data] in the controller, you need to specify that {data: dummy} in the AJAX data section
<script type="text/javascript">
var dummy = "testtext";
$('#finish').click(function() {
$.ajax( {
url: '/finish',
type: 'POST',
data: {data: dummy},
dataType: 'text'
});
});
</script>
Also you might want to respond to your AJAX call in your controller using the following
def finish
#data = params[:data]
respond_to do |format|
format.json { insert_your_code_here }
end
end
Say I have a button on my form, it doesn't submit the form, but it basically goes off to get some more information:
<%= f.button '', class:'hidden', id: 'do_calculation', remote: true %>
How do I tie this up so that when it is clicked it calls a controller action and returns the data?
Should I have something like this on the same page?
<script>
function calculate_close() {
var id = '<%= #thing.id %>';
$.ajax({
url: "<%= calculate_path %>",
data: {
id: id
},
dataType: "script"
})
}
</script>
Here you can create a html button without using form builder like.
<button id="do_calculation">Button</button>
Then you can bind the click event to that button and call the ajax inside that event, like:
$("#do_calculation").on('click', function(){
var id = '<%= #thing.id %>';
$.ajax({
url: "<%= calculate_path %>",
data: {
id: id
},
dataType: "json"
})
})
and in the controller you can use something like:
respond_to do |format|
format.json { render :json => {:message => "success"} }
end
Hope this will help!
I am trying to pass some parameters from my view via an AJAX call to a custom method fetch_info in my photos controller. My controller does not seem to be receiving the parameters. When I click on an image to initiate the AJAX call, I see the following in my terminal:
Processing by PhotosController#fetch_info as JSON
Parameters: {"id"=>"", "secret"=>""}
Completed 500 Internal Server Error in 267ms
FlickRaw::FailedResponse ('flickr.photos.getInfo' - Photo not found):
app/controllers/photos_controller.rb:38:in `fetch_info'
It looks like the fetch_info method is being called, but the parameters are empty. How should I be passing in my parameters through AJAX?
Here is my view. I also have my javascript in the view for the purpose of just getting this to work.
index.html.erb
<div class="body_container">
<div id="photos_container">
<% #photos_array.each do |p| %>
<%= link_to '#' do %>
<div class='each_photo_container', id='<%="#{p[:id]}"%>' >
<%= image_tag p[:s_url] %>
</div>
<% end %>
<!-- Load Modal onClick -->
<script type="text/javascript">
jQuery(function() {
$('#<%=p[:id]%>').click(function (e) {
//ajax call to fetch photo info
var fetch_id = '<%=p[:id]%>';
var fetch_secret = '<%=p[:secret]%>';
$.ajax({
type: 'GET',
url: '/photos/fetch_info',
dataType: 'json',
data: { 'id' : fetch_id.val(), 'secret' : fetch_secret.val() }
});
return false;
});
});
</script>
<% end %>
<div class="basic_modal">
</div>
</div>
</div>
Here is my photos_controller.rb:
def fetch_info
puts params[:id]
puts params[:secret]
info = flickr.photos.getInfo(:photo_id => params[:id], :secret=> params[:secret])
end
You can use this code:
$('##{p[:id]}').click(function (e) {
//ajax call to fetch photo info
var fetch_id = '#{p[:id]}';
var fetch_secret = '#{p[:secret]}';
$.ajax({
type: 'GET',
url: '/photos/fetch_info',
dataType: 'json',
data: { 'id' : fetch_id, 'secret' : fetch_secret }
});
return false;
})