Rails + Vue.js - Using Ajax to update Vue component
Asked Answered
F

1

14

I have a Rails 5 app using webpacker that displays a list of users. The logic to do so is in a partial that has Vue component code in it, like

<profile_modal>

  <template slot="trigger">

    <figure class="profile-card__figure | image -is1x1">
      <img src="<%= person.avatar.url %>" alt="">
    </figure>
...

Everything works well, and the .erb changes this correctly to HTML when the page is processed. So far so good.

Now I've added a button that says "show more users" that makes an ajax call to pull in more users. I've made a js.erb that has in it:

$("#users").html("<%= escape_javascript(render partial: 'layouts/components/profile-card--modal', collection: @users.last(12), as: :person, locals: { content: @users_presenter.profile_modal }) %>"); 

This code is executed, but instead of converting the "profile_modal" to the right html, rails is just inserting it right in the page, which makes everything wrong.

Is there a way I can have the vue code be transpiled into the html it would become during normal, non-ajaxy processing?

Featheredge answered 7/5, 2019 at 17:12 Comment(4)
To break down your steps, You made a button show more users that makes an ajax call to yourfile.js.erb. The file includes the following javascript $("#users").html(....) which appends to #users the html from partial profile-card--modal with the data of @users.last(12). This last step is not clear to me. This code is executed, but instead of converting the "profile_modal" to the right html, rails is just inserting it right in the page, which makes everything wrong. it would be useful to see the actual effect you are describing with a screenshot or the actual source code. ThanksGaga
@FabrizioBertoglio Sorry for the lack of clarity. The partial is successfully added to the DOM and makes it onto the page as one would expect. However, instead of the partial code, which contains Vue stuff like "<profile_modal>", being changed to proper HTML as it is in the same code in the html.erb, the code is spit out as is and thus when you inspect the result of the ajax call in the browser you see the tag "<profile_modal>" in the code, which obviously isn't correct. Hopefully that explanation makes sense. Thanks!Featheredge
<profile_modal> is some sort of component, which javascript should replace with html but instead it gets directly appended to the page when you run $("#users").html(). You have this problem only with asynchronous javascript request which do not run a full page reload? This means that we can isolate the problem to Webpacker with Vue not working correctly? You are replying with rails controller in javascript format and using an .erb.js view.Gaga
are you using server or client rendering with vue? If it is client rendering, Vue may have a listener on the page to detect changes and execute javascript to render the vue component. I believe server rendering would not need the client to run javascript to render the html and you would not experience this problem.Gaga
J
3

You shouldn't call a render for a whole component, you should instead make a global component that receives an array of users as variable, something in the lines of:

window.users = [
  { id: 'this-is-an-id', name: 'Evan', age: 34 },
  { id: 'unique-id', name: 'Sarah', age: 98 },
  { id: 'another-unique-id', name: 'James', age: 45 },
];

<ul>
  <li v-for="person in users" :key="person.id">
    {{ person.name }} - {{ person.id }}
  </li>
</ul>

Then when you change the users variable, your Vue component will change too. So instead of overriding the whole HTML for the component, make you .js.erb append to users variable:

response_users = <%=j @users.last(12).as_json %>;
Object.assign(users, response_users);
Joeljoela answered 13/5, 2019 at 17:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.