I have a Rails partial I am attempting to populate and display based on a Ajax response but it seems the instance variable is not being updated. I know I’m missing something.
It might be due to the fact that I’m using a different controller for the view than the ajax call.
When my view instantiates, I provide a value for @ingredients
or else my partial throws an error:
# RecipesController#new
def new
@recipe = Recipe.new
@ingredients = []
end
Here’s the ajax function that is called when the user clicks a button:
$('.ingredientContainer').on('click', '.searchForIngredient', function(e) {
e.preventDefault();
const ingredientName = $(this).parents('fieldset').find('.ingredient-item').val()
$.ajax({
method: 'post',
url: '/ingredients/search',
data: {
name: ingredientName
},
success: (res) => {
// This displays the correct response
console.log("res", res)
// This prints [] as if @ingredients has not changed
console.log("<%= @ingredients %>")
$('.ingredientSelectionModalBody').html("<%= j(render partial: 'ingredient_search_table', locals: {ingredient_array: @ingredients}) %>")
$('.ingredientModal').modal({show: true})
}
})
})
Here’s the IngredientsController
that is called from the Ajax request and where I expect to define the value of @ingredients
:
class IngredientsController < ApplicationController
def search
@ingredients = Tools.searchForIngredient(params['name'])
end
end
Here’s my partial that is rendered into a modal’s body:
<table class="table table-awaken">
<thead>
<th>Name</th>
<th>Brand</th>
<th>Description</th>
</thead>
<tbody>
<%= ingredient_array.inspect %>
<% ingredient_array.each do |ingredient| %>
<tr>
<td><%= ingredient.name %></td>
<td><%= ingredient.brand %></td>
<td><%= ingredient.description %></td>
</tr>
<% end -%>
</tbody>
</table>
The issue is that the view is not aware the value of @ingredients
has been updated and I’m not sure how to fix that so that the response from IngredientsController
can be displayed.
2
Answers
I was able to solve my problem by moving the DOM modification javascript into the file being rendered by the
IngredientsController
. I generated a filesearch.js.erb
with the following content:Since this is rendered after
@ingredients
has been updated, the new data from the controller is available.The
console.log("<%= @ingredients %>")
is from the JS viewpoint hardcoded asconsole.log("[]")
when the page is initially rendered. You can check it if you inspect the page and find the code in the loaded assets.The get the actual data you have to return it as a response to the
/ingredients/search
call. Make the request of typeapplication/json
and return something likerender json: @ingredients
from your controller. Then on the frontend you should have these data in theres
variable so use that instead of<%= @ingredients %>