Using the AJAX functionality to create a 'delete' button in a Rails application is a powerful

I'm having difficulty with an ajax-based 'delete' button.

While the button successfully deletes the object from my database, it doesn't update the index page. This means that the deleted object remains visible on the index until the page is manually refreshed.

In my view:

<%= link_to "Delete Fabric", delete_fabric_path(fabric), method: :delete, data: { confirm: 'Are you sure?' }, :remote => true, :class => 'delete_fabric', class: "btn btn-primary btn-sm"%>

Routes:

delete "/fabrics/:id" => "fabrics#destroy", as: 'delete_fabric'
get "/fabrics/collection" => "fabrics#index", as: "index_fabrics"

Controller:

def destroy
  @fabric = Fabric.find(params[:id])
  @fabric.destroy

  respond_to do |format|
    format.html { redirect_to index_fabrics_url }
    format.json { head :no_content }
    format.js { render layout: false }
  </end>

destroy.js.erb:

$('.delete_fabric').bind('ajax:success', function() {
  $(this).closest('tr').fadeOut();
});

If anyone can pinpoint where I've gone astray, I'd greatly appreciate it! Many thanks.

This is the tutorial I was following.

Server logs:

Started DELETE "/fabrics/46" for 127.0.0.1 at 2018-08-17 15:57:22 +0800
Processing by FabricsController#destroy as JS
  Parameters: {"id"=>"46"}
  Fabric Load (1.4ms)  SELECT  "fabrics".* FROM "fabrics" WHERE "fabrics"."id" = $1 LIMIT $2  [["id", 46], ["LIMIT", 1]]
  ↳ app/controllers/fabrics_controller.rb:70
   (0.4ms)  BEGIN
  ↳ app/controllers/fabrics_controller.rb:71
  Fabric Destroy (0.5ms)  DELETE FROM "fabrics" WHERE "fabrics"."id" = $1  [["id", 46]]
  ↳ app/controllers/fabrics_controller.rb:71
   (6.3ms)  COMMIT
  ↳ app/controllers/fabrics_controller.rb:71
  Rendering fabrics/destroy.js.erb
  Rendered fabrics/destroy.js.erb (9.4ms)
Completed 200 OK in 83ms (Views: 30.4ms | ActiveRecord: 8.6ms)

Full view:

<!-- SHOW FABRIC COLLECTION / FABRIC OPTIONS-->

<div class="card-deck">

    <% @fabrics.each do |item| %>

        <div class="col-sm-6 col-md-4 col-lg-3">
          <div class="card" style="width: 18rem;">
            <img class="card-img-top" src="<%=fabric.image%>">
            <div class="card-body">
              <h5 class="card-title"><%= fabric.fabric_name%></h5>
              <p class="card-text"><%= fabric.fabric_description%></p>
              <p class="card-text"><%= fabric.printed%></p>


<!--               Listing fibre types -->
              <p class="card-text"><small class="text-muted">Composition: 

                        <% fabric.fibre.each do |fibre| %>
                            <%=fibre %>
                        <%end%>
              </small></p>


<!--               Listing colours -->
              <p class="card-text"><small class="text-muted">Colours: 

                        <% fabric.colour.each do |colour| %>
                            <%=colour %>
                        <%end%>
              </small></p>


<!--               Listing suitable for -->
              <p class="card-text"><small class="text-muted">Suitable For: 

                        <% fabric.suitable_for.each do |item| %>
                            <%=item %>
                        <%end%>
              </small></p>

<!--               Show page button -->
      <%= link_to "Full Details", show_fabrics_path(fabric), class: "btn btn-primary btn-sm" %>

<!--              AJAX DELETE BUTTON IN PROGRESS-->

       <%= link_to "Delete Fabric", delete_fabric_path(fabric), method: :delete, data: { confirm: 'Are you sure?' }, :remote => true, :class => 'delete_fabric'%>

<!--              AJAX DELETE BUTTON -->

            </div>
           </div>
      </div>

    <% end %>

</div>

Answer №1

Rolandas has provided a solution that should assist you in resolving your issue.

It appears that the deletion is functioning correctly on the server side, and you are rendering the appropriate partial (the destroy.js.erb file.)

For additional debugging, consider adding

console.log($(this).closest('tr'))
to your event listener for the ajax success.

Your javascript should resemble the following:

console.log('Binding event');
$('.delete_fabric').bind('ajax:success', function() {
  console.log('fading the element: ', $(this).closest('tr')); 
  $(this).closest('tr').fadeOut();
});
  • If you do not see a log in your JS console, it indicates that you may not be listening to the correct event.
  • If you see the console log, examine the element being faded out, and confirm that it is the Fabric you have just destroyed.

Answer №2

You have duplicated the class definition:

:class => 'delete_fabric', class: "btn btn-primary btn-sm"

Consider merging them into a single line:

class: "btn btn-primary btn-sm delete_fabric"

Answer №3

Assign a unique id to each fabric record like this: (id="fabric_<%=fabric.id%>")

<!-- DISPLAY FABRIC COLLECTION / FABRIC OPTIONS-->
<div class="card-deck">
  <% @fabrics.each do |fabric| %>
  <div class="col-sm-6 col-md-4 col-lg-3" id="fabric_<%=fabric.id%>">
    <div class="card" style="width: 18rem;">
      <img class="card-img-top" src="<%=fabric.image%>">
      <div class="card-body">
        <h5 class="card-title"><%= fabric.fabric_name%></h5>
        <p class="card-text"><%= fabric.fabric_description%></p>
        <p class="card-text"><%= fabric.printed%></p>
        <!--Listing fibre types -->
        <p class="card-text"><small class="text-muted">Composition: 
          <% fabric.fibre.each do |fibre| %>
          <%=fibre %>
          <%end%>
          </small>
        </p>
        <!--Listing colours -->
        <p class="card-text"><small class="text-muted">Colours: 
          <% fabric.colour.each do |colour| %>
          <%=colour %>
          <%end%>
          </small>
        </p>
        <!--Listing suitable for -->
        <p class="card-text"><small class="text-muted">Suitable For: 
          <% fabric.suitable_for.each do |item| %>
          <%=item %>
          <%end%>
          </small>
        </p>
        <!--Display full details button -->
        <%= link_to "Full Details", show_fabrics_path(fabric), class: "btn btn-primary btn-sm" %>
        <!--AJAX DELETE BUTTON IN PROGRESS-->
        <%= link_to "Delete Fabric", delete_fabric_path(fabric), method: :delete, data: { confirm: 'Are you sure?' }, :remote => true, :class => 'delete_fabric'%>
        <!--AJAX DELETE BUTTON -->
      </div>
    </div>
  </div>
  <% end %>
</div>

In the controller:-

def destroy
  @fabric = Fabric.find(params[:id])
  if @fabric.destroy
    flash[:success] = "Fabric deleted successfully!"
  end

  respond_to do |format|
    format.html { redirect_to index_fabrics_url }
    format.json { head :no_content }
    format.js { render layout: false }
  end

In destroy.js.erb

<%if flash[:success].present?%>
  $("#fabric_<%=params[:id]%>").fadeOut();
  //$("#fabric_<%=params[:id]%>").remove();
<%end%>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A convenient Delete Modal Component in React utilizing Reactstrap

I am currently working on implementing a reusable Delete Component using reactstrap, which can be called from other components. Below is the code for my DeleteModal: class DeleteModal extends Component { constructor(props) { super(props); this. ...

Tips for adjusting the margin of a print document in a printTask?

Is there a way to achieve a borderless print? Currently, my printed output has a border around it. I would like the image to start at the top left corner without any borders. I attempted to set a negative margin to the print-style box, but it resulted in ...

Executing several GET requests in JavaScript

Is there a more efficient way to make multiple get requests to 4 different PHP files within my project and wait for all of them to return successfully before appending the results to the table? I have tried nesting the requests, but I'm looking for a ...

"Utilizing Object.call() in JavaScript for inheritance yields an undefined result

I have been working on implementing an object-oriented approach in my program. According to what I've learned, there should be an inheritance relationship between World and Sprite classes, with Sprite as the parent. However, when I try to call Sprite. ...

What is the optimal method for organizing JavaScript and CSS files within my Play2 application?

Trying to figure out the best way to organize my js and css files for my app. If I examine the structure of a play2 app: app → Source code for the application └ assets → Compiled asset sources └ stylesheets ...

Managing deeply nested state updates in Redux using the spread operator

As I develop a large web application using react+redux, managing my store has become quite complex. I encountered an issue with updating nested properties in the store and came across the Immutable Update Patterns section of the redux documentation. It su ...

Prevent user input in Vue.js until the value has been modified

Need help handling initial input values: <input type="text" v-model="name" ref="input" /> <button type="submit" :disabled="$refs.input.defaultValue == $refs.input.value">Submit</button> Encountering an error with the disabled binding: C ...

What is the process for connecting this to React ES6 getter and setter methods?

When utilizing this within an ES6 function, it is necessary to explicitly declare it in the constructor. export class MyComponent extends React.Component { constructor(){ super(); this.myFunc = this.myFunc.bind(this); } ...

Creating a process to automatically generate an input field upon the selection of checkboxes

Is there a way to automatically generate a text field for each checked box in a dynamically changing checkbox list? Below is my code snippet: <div> <label> Products </label> <li ng-repeat="item in INDproducttypes"> ...

Shopify private app experiencing issues with AJAX functionality, although CURL requests are functioning properly

After developing a private app on my store, I attempted to access the URL using both ajax and curl. Surprisingly, it functions properly when utilizing curl, but encounters issues with ajax. Can someone shed light on what might be causing this discrepanc ...

The prop type 'lg' supplied to 'ForwardRef(Grid)' is not valid and has failed

This particular code snippet is responsible for managing the layout of components on the webpage. However, I have encountered some warning messages in the console: Warning: Failed prop type: The lg prop provided to ForwardRef(Grid) is invalid, it should ...

Create an AngularJS Directive that will display an array of n elements in the form of m rows of tables

Challenge: I have an array of 'n' items that I need to display in separate tables, with each table containing m rows. For instance, if n=30 and m=6, then I should have 5 tables each with 6 items displayed horizontally. Proposed Solution: I attem ...

Is it possible to authenticate across multiple tables in a React/Node.js environment?

I am currently planning an online library management system project. For this project, I have identified **3 distinct roles** which are stored in separate database tables. Firstly, there is the user role, which will have an interface allowing them to view ...

Utilize a pipe to seamlessly transfer data from MSSQL to a Node.js application

I am currently utilizing node along with node-mssql version 6.0.1 for handling large amounts of data retrieval from the database and transmitting it to the frontend using streams. Although I have attempted to implement pipe and stream functionality as rec ...

HTML forms default values preset

I need help with pre-setting the values of a dropdown menu and text box in an HTML form for my iPhone app. When the user taps a button, it opens a webview and I want to preset the dropdown menu and text field. Can someone guide me on how to achieve this? ...

Changing Text to Number in JavaScript

Looking to convert the string value of 41,123 into an integer using JavaScript. I attempted parseInt(41,123, 10) and parseFloat methods but haven't received the desired result. The issue seems to be with ParseInt and parseFloat when encountering com ...

Creating custom functions within views using Sencha Touch 2

I'm having trouble creating my own function in Sencha Touch 2 and I keep receiving an error: Uncaught ReferenceError: function22 is not defined The issue seems to be coming from my Position.js file located in the View directory. Ext.define(' ...

The error message states: `discord.js TypeError: Unable to access the property 'resolve' as it is undefined`

Encountering an issue with the following code snippet const Discord = require('discord.js'); module.exports = { name: 'info', description: "Shows BOT's Informations", execute(message, client, args) { c ...

How can I integrate date and time pickers in the view using CodeIgniter?

Trying to add date and time data into the database using a date and time picker. After dumping the results in the controller to ensure all fields are selected, I encountered an issue where only the time is being picked and the data is not being inserted. T ...

Zend Framework causing issues with Jquery Ajax - encountering parsererror with Json output

I'm new to using the zend framework and am struggling to pass an array from a controller to a jQuery AJAX function in the view. I keep receiving errors when I change the 'dataType' to 'json'. Can someone please help me understand ...