skip to Main Content

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


  1. Chosen as BEST ANSWER

    I was able to solve my problem by moving the DOM modification javascript into the file being rendered by the IngredientsController. I generated a file search.js.erb with the following content:

    $('.ingredientSelectionModalBody').html("<%= j(render 'recipes/ingredient_search_table', ingredient_array: @ingredients) %>")
    $('.ingredientModal').modal({show: true})
    

    Since this is rendered after @ingredients has been updated, the new data from the controller is available.


  2. The console.log("<%= @ingredients %>") is from the JS viewpoint hardcoded as console.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 type application/json and return something like render json: @ingredients from your controller. Then on the frontend you should have these data in the res variable so use that instead of <%= @ingredients %>

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search