質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

0回答

2196閲覧

【Rails 5.1.6 + Vue.js】新規登録画面への遷移について

tenten11055

総合スコア67

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2019/11/19 09:53

編集2019/11/21 09:58

#現状起きていること
RailsとVue.jsでCURDを備えたアプリを作っていたのですが、
新規登録画面を作成中に問題が起こりました。

一覧画面から新規登録画面(localhost:3000/#/projects/new)に遷移すると、
URLは正しく表示されているのですが画面が詳細画面(/projects/:id)になってしまいます。
もちろんこの時IDを取得するメソッドは書いていないので、項目名しか表示されません。

またその画面でコンソールを開くと下記のエラーがでていました。

xhr.js:166 GET http://localhost:3000/api/projects/new.json 404 (Not Found) createError.js:17 Uncaught (in promise) Error: Request failed with status code 404 at createError (createError.js:17) at settle (settle.js:19) at XMLHttpRequest.handleLoad (xhr.js:60)

xhr.js:166 GET http://localhost:3000/api/projects/new.json 404 (Not Found)
こちらに関して、なぜGETパラメータになっていて、なぜnew.jsonを呼ぼうとしているのかが分かりません。
そもそもnew.jsonというものはないのでエラーになって当然なのです。

またボタンからの遷移、URL直打ち両方で同様のエラーに遭遇します。

#解決したいこと
詳細画面ではなく、ちゃんと新規登録画面に遷移できるようにしたい。

#関与しそうなソース
####projects.vue(一覧画面 ちゃんと開ける)

<template> <div id = 'project'> <h1>プロジェクト一覧</h1> <div class = 'new-link-btn'> <router-link to="/projects/new" class='btn waves-effect waves-light'><i class="material-icons left">cloud</i>新規登録</router-link> </div> <table> <tbody> <tr> <th>プロジェクト名</th> <th>担当部署</th> <th>売上金額</th> <th>開始日</th> <th>終了日</th> <th></th> </tr> <tr v-for="project in projects" :key="project.id"> <td>{{ project.project_name }}</td> <td>{{ project.department }}</td> <td>{{ project.amount }}</td> <td>{{ project.start_date }}</td> <td>{{ project.end_date }}</td> <th><router-link :to="{name: 'Project', params: {id: project.id}}" class="btn btn-info">詳細</router-link></th> </tr> </tbody> </table> </div> </template> <script> import axios from 'axios' export default { data: function() { return { projects: [] } }, mounted: function() { this.fetchProjects(); }, methods: { fetchProjects: function() { axios.get('api/projects.json').then(response => (this.projects = response.data)); } } } </script> <style scoped> p { font-size: 2em; text-align: center; } h1 { font-size: 40px; text-align: center; padding-bottom: 20px; } .new-link-btn { text-align: end; } </style>

####project.vue(詳細画面 ちゃんと開ける)

<template> <div id = 'project-show'> <dl> <dt>プロジェクト名</dt> <dd>{{ project.project_name }}</dd> <dt>担当部署</dt> <dd>{{ project.department }}</dd> <dt>売上金額</dt> <dd>{{ project.amount }}</dd> <dt>開始日</dt> <dd>{{ project.start_date }}</dd> <dt>終了日</dt> <dd>{{ project.end_date }}</dd> </dl> <div class = 'history-back-btn'> <a @click="$router.go(-1)" class="btn">戻る</a> </div> </div> </template> <script> import axios from 'axios'; export default { data: function() { return { project: {} } }, mounted: function() { this.fetchProject(); }, methods: { fetchProject: function() { axios.get(`/api/projects/${this.$route.params.id}.json`) .then(response => (this.project = response.data)) } } } </script> <style scoped> </style>

####create_project.vue(新規登録画面 問題の画面)

<template> <form @submit.prevent="createProject"> <div v-if="errors.length != 0"> <ul v-for="error in errors" :key="error"> <li><font color="red">{{ error }}</font></li> </ul> </div> <div> <label>プロジェクト名</label> <input v-model="project.name" type="text"> </div> <label>担当部署</label> <select v-model="project.department"> <option>開発</option> <option>デザイン</option> <option>マーケティング</option> <option>その他</option> </select> <div> <label>売上金額</label> <input v-model="project.amount" type="number" min="0" max="999999999"> </div> <div> <label>開始日</label> <input v-model="project.start_date" type="date"> </div> <div> <label>終了日</label> <input v-model="project.end_date" type="date"> </div> <button type="submit" class="btn btn-submit">登録</button> </form> </template> <script> import axios from 'axios'; export default { data: function() { return { project: { project_name: '', department: '', amount: '', start_date: '', end_date: '' }, errors: '' } }, methods: { createProject: function() { axios.post('/api/projects', this.project) .then(response => { let project = response.data; this.$router.push({ name: 'Project', params: { id: project.id } }); }) .catch(error => { console.error(error); if(error.response.data && error.response.data.errors) { this.errors = error.response.data.errors } }); } } } </script> <style scoped> </style>

####router.js

import Vue from 'vue' import VueRouter from 'vue-router' import Index from '../components/index.vue' import About from '../components/about.vue' import Contact from '../components/contact.vue' import Projects from '../components/projects/projects.vue' <- 一覧画面 import Project from '../components/projects/project.vue' <- 詳細画面 import CreateProject from '../components/projects/create_project.vue' <- 新規登録画面 Vue.use(VueRouter); // mode: 'history', const routes = [ { path: '/', component: Index }, { path: '/about', component: About }, { path: '/contact', component: Contact }, { path: '/projects', component: Projects, name: 'Projects' }, { path: '/projects/:id', component: Project, name: 'Project' }, { path: '/projects/new', component: CreateProject, name: 'CreateProject' } ]; export default new VueRouter({ routes })

####controllers/api/projects_controller.rb

class Api::ProjectsController < ApplicationController before_action :set_project, only: [:show] # 拾えなかったExceptionが発生したら500 Internal server errorを応答する rescue_from Exception, with: :render_status_500 # ActiveRecordのレコードが見つからなければ404 not foundを応答する rescue_from ActiveRecord::RecordNotFound, with: :render_status_404 def index projects = Project.all render json: projects end def show render json: @project end def create project = Project.new(project_params) if project.save render json: project, status: :created else render json: { errors: project.errors.full_messages }, status: :unprocessable_entity end end private def set_project @project = Project.find(params[:id]) end def project_params params.fetch(:project, {}).permit(:project_name, :department, :amount, :start_date, :end_date) end def render_status_404(exception) render json: { errors: [exception] }, status: 404 end def render_status_500(exception) render json: { errors: [exception] }, status: 500 end end

####routes.rb

Rails.application.routes.draw do # get 'home/index' root to:"home#index" get '/projects', to: 'home#index' get '/projects/:id', to: 'home#index' get '/projects/new', to: 'home#index' namespace :api, format: 'json' do resources :tasks, only: [:index, :create, :update] resources :projects, only: [:index, :show, :create] end end

####javascript/packs/todo.js(viewやコンポーネントを定義しているjsファイル)

import Vue from 'vue' import Router from './router/router' import Header from './components/header.vue' var app = new Vue({ router: Router, el: '#app', components: { 'navbar': Header, } });

####views/home/index.html.erb

<div id="app"> <navbar></navbar> <div class = 'container'> <router-view></router-view> </div> </div> <%= javascript_pack_tag 'todo' %>

宜しくお願い致します。

#2019.11.21 追記
router-linkを名前付きルートにしたところうまくいきました。
####projects.vue
ここを

<router-link to="/projects/new" class='btn waves-effect waves-light'><i class="material-icons left">cloud</i>新規登録</router-link>

こうした

<router-link :to="{ name: 'CreateProject' }" class='btn waves-effect waves-light'><i class="material-icons left">cloud</i>新規登録</router-link>

しかし、URL直打ちで画面遷移しようとすると詳細画面に行ってしまいます。
なぜこのような現象が起こるのか、不明のままです。
ご回答募集しております。。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問