axios 如何在Rails 7应用中使用javascript更改svg click上的文本标签?

gcuhipw9  于 2023-01-30  发布在  iOS
关注(0)|答案(1)|浏览(115)

用户可以单击复选标记图标将公园标记为已访问(灰色复选标记)或未访问(绿色复选标记)。
我还想让复选标记图标旁边的文本在用户每次单击复选标记时都发生变化(在“已访问”和“未访问”之间)-如果文本也是可单击区域的一部分,效果会更好。
我是新的Javascript,所以我相信这是基本的,但我不知道如何做到这一点。

javascript/控制器/访问控制器.js

import { Controller } from '@hotwired/stimulus';
import axios from 'axios';

export default class extends Controller {
  HEADERS = { 'ACCEPT': 'application/json' };

  visit() {
    if (this.element.dataset.userLoggedIn === 'false' ) {
      return document.querySelector(".sign-in-link").click();
    }

    if (this.element.dataset.visited === 'true') {
      this.unvisitPark();
    } else {
      this.visitPark();
    }
  }

  getVisitPath() {
    return '/api/visits';
  }

  getUnvisitPath(visitId) {
    return `/api/visits/${visitId}`
  }

  unvisitPark() {
    axios.delete(this.getUnvisitPath(this.element.dataset.visitId), {
      headers: this.HEADERS
    })
    .then((response) => {
      this.element.dataset.visited = 'false'
      this.element.dataset.visitId = '';
      this.element.setAttribute('stroke', '#D3D3D3');
      this.element.setAttribute('stroke-width', '2');
    });
  }

  visitPark() {
    axios.post(this.getVisitPath(), {
      user_id: this.element.dataset.userId,
      park_id: this.element.dataset.parkId
    }, {
      headers: this.HEADERS
    })
    .then((response) => {
      this.element.dataset.visited = 'true'
      this.element.dataset.visitId = response.data.id;
      this.element.setAttribute('stroke', '#5FA777');
      this.element.setAttribute('stroke-width', '4');
    });
  }
}

视图/公园/_公园_卡片.erb

<% @parks.each do |park| %>
...
  <div class="mt-1">
    <span>Visited</span> // <-- Make this text change whenever the svg is clicked
    <div class="btn p-0 mb-2">
      <svg
           data-controller="visits"
           data-user-logged-in="<%= user_signed_in? %>"
           data-user-id="<%= current_user&.id %>"
           data-park-id="<%= park.id %>"
           data-visit-id="<%= park.visits.find_by(user: current_user)&.id %>"
           data-visited="<%= park.visited_by?(current_user) %>"
           data-action="click->visits#visit"
           stroke="<%= current_user && current_user.visited_parks.include?(park) ? '#5FA777' : '#D3D3D3' %>"
           stroke-width="<%= current_user && current_user.visited_parks.include?(park) ? 4 : 2 %>"
           fill="none"
           width="24"
           height="24"
           xmlns="http://www.w3.org/2000/svg"
           viewBox="0 0 24 24"
           class="w-6 h-6">
           <path
             stroke-linecap="round"
             stroke-linejoin="round"
             d="M4.5 12.75l6 6 9-13.5" />
       </svg>
     </div>
   </div>
...
<% end %>
q9rjltbz

q9rjltbz1#

通过向SVG本身添加文本,我已经非常接近于我想要的效果。
然而,我仍然在为间距而挣扎,如果使用图像内的文本而不是作为单独的文本字段,可能会有一个可访问性问题。
我希望有人会贡献一个答案使用应用程序文本大鼠,但如果有人正在阅读本文,并希望使用这种方法,这里是:

<% @parks.each do |park| %>
...
  <div class="btn p-0 mb-2">
    <svg
         data-controller="visits"
         data-user-logged-in="<%= user_signed_in? %>"
         data-user-id="<%= current_user&.id %>"
         data-park-id="<%= park.id %>"
         data-visit-id="<%= park.visits.find_by(user: current_user)&.id %>"
         data-visited="<%= park.visited_by?(current_user) %>"
         data-action="click->visits#visit"
         stroke="<%= current_user && current_user.visited_parks.include?(park) ? '#5FA777' : '#D3D3D3' %>"
         stroke-width="<%= current_user && current_user.visited_parks.include?(park) ? 4 : 3 %>"
         fill="none"
         width="160"
         height="24"
         xmlns="http://www.w3.org/2000/svg"
         viewBox="0 0 24 24"
         class="w-6 h-6">
         <path
           stroke-linecap="round"
           stroke-linejoin="round"
           d="M4.5 12.75l6 6 9-13.5" />
        <text
          id="visited-text"
          x="-68"
          y="18"
          stroke="currentColor"
          fill="currentColor"
          stroke-width="0"
          class="link-dark">
            <%= current_user && current_user.visited_parks.include?(park) ? "Visited" : "Not visited" %>
        </text>
     </svg>
   </div>
...
<% end %>
import { Controller } from '@hotwired/stimulus';
import axios from 'axios';

export default class extends Controller {
  HEADERS = { 'ACCEPT': 'application/json' };

  visit() {
    if (this.element.dataset.userLoggedIn === 'false' ) {
      return document.querySelector(".sign-in-link").click();
    }

    if (this.element.dataset.visited === 'true') {
      this.unvisitPark();
    } else {
      this.visitPark();
    }
  }

  getVisitPath() {
    return '/api/visits';
  }

  getUnvisitPath(visitId) {
    return `/api/visits/${visitId}`
  }

  unvisitPark() {
    axios.delete(this.getUnvisitPath(this.element.dataset.visitId), {
      headers: this.HEADERS
    })
    .then((response) => {
      this.element.dataset.visited = 'false'
      this.element.dataset.visitId = '';
      this.element.setAttribute('stroke', '#D3D3D3');
      this.element.setAttribute('stroke-width', '2');
      this.element.getElementById('visited-text').textContent = "Not visited";
    });
  }

  visitPark() {
    axios.post(this.getVisitPath(), {
      user_id: this.element.dataset.userId,
      park_id: this.element.dataset.parkId
    }, {
      headers: this.HEADERS
    })
    .then((response) => {
      this.element.dataset.visited = 'true'
      this.element.dataset.visitId = response.data.id;
      this.element.setAttribute('stroke', '#5FA777');
      this.element.setAttribute('stroke-width', '4');
      this.element.getElementById('visited-text').textContent = "Visited";
    });
  }
}

相关问题