Ruby on Railsのlink_to
には、method
を指定してGET以外のリクエストを送信する機能があります。Viewを含めてフロント周りをVue.jsに置き換えるときに、この辺りの再現がネックになったのでVue.jsでの再現方法をメモ📝
You can bind to the same Ajax events as form_with. Here's an example. Let's assume that we have a list of articles that can be deleted with just one click. We would generate some HTML like this:
<%= link_to "Delete article", @article, remote: true, method: :delete %>
前提事項
以下の記事で記載したFormコンポーネントが存在することが前提です。
<template> <form ref="form" class="common-form" :action="requestPath" accept-charset="UTF-8" :method="formMethod"> <input type="hidden" name="_method" :value="requestMethod" autocomplete="off" /> <input type="hidden" name="authenticity_token" :value="authenticityToken" autocomplete="off" /> <slot /> </form> </template> <script setup lang="ts"> import { computed, ref } from "vue"; type Props = { requestMethod: "get" | "post" | "patch" | "put" | "delete"; requestPath: string; }; const csrfToken = () => { const meta = document.querySelector("meta[name=csrf-token]"); return meta && (meta as HTMLMetaElement).content; }; const props = defineProps<Props>(); const authenticityToken = csrfToken(); const formMethod = computed(() => (props.requestMethod === "get" ? "get" : "post")); const form = ref<HTMLFormElement | null>(null); defineExpose({ form }); </script> <style lang="scss" scoped></style>
実装したコード
以下のようなコンポーネントを用意して再現してみました。仕組みはget以外の場合には前提に記載したCommonForm
を非表示要素として入れて、
a
タグクリックのeventをpreventし、Formをsubmitイベントを呼び出すようにしています。
<template> <a v-if="method === 'get'" class="common-link" :href="href"> <slot /> </a> <a v-else class="common-link" @click.prevent="handleOnSubmit"> <slot /> <CommonForm ref="linkForm" class="common-link__link-form" :request-method="method" :request-path="href" /> </a> </template> <script lang="ts" setup> import type { HttpRequestMethod } from "@js/types/types"; import CommonForm from "@js/components/molecules/CommonForm.vue"; import { ref } from "vue"; type PropsType = { href: string; method?: HttpRequestMethod }; withDefaults(defineProps<PropsType>(), { method: "get" }); const linkForm = ref<InstanceType<typeof CommonForm> | null>(null); const handleOnSubmit = (_e: Event) => { // NOTE: CommonFormのformをsubmitする linkForm.value?.form?.submit(); }; </script> <style lang="scss" scoped> @use "@css/variables" as *; .common-link { &__link-form { display: none; } } </style>
以下のような感じで利用することができます。
<CommonLink :href="/sessions" method="delete">ログアウト</CommonLink>