Ask A Question

Notifications

You’re not receiving notifications from this thread.

How do I get redirect to view after create action using Vue.js

Tabish Iqbal asked in Javascript

Out of interest, have a weird issue. Trying to do a redirect after create. The record is being created just fine, but get a 500 error on the redirect? Using an ajax call using Vue-resource. Below is the code. (gist for better readability : https://gist.github.com/tabishiqbal/6c3839e53b5c5d34f0cbcc98185bb326)

CREATE METHOD IN CONTROLLER

def create
  @proposal = @project.proposals.create(proposal_params)
  authorize @proposal
  respond_to do |format|

    if @proposal.save!
      format.html { redirect_to project_proposal_path(@proposal.project, @proposal), notice: "Proposal successfully created and submitted to the client" }
      format.json { render :show, status: :created, location: @proposal }
      @project.update_attribute(:status_id, set_quote_ready)

      # As there is a new final, all previous versions are no longer current
      @project.proposals.where.not(id: @proposal.id).update_all(current: false)

      # Set this new final version as the current version
      if @project.proposals.all_final.count > 1
        @user.notify_user("#{@project.supplier.display_name} has updated their proposal. Check it out!", @project.id)
        @project.supplier.notify_business("Your revised proposal has been submitted to the client for approval", @project.id)
      else
        @user.notify_user("#{@project.supplier.display_name} has submitted a proposal for your project. Accept it to start the project", @project.id)
        @project.supplier.notify_business("Your proposal has been submitted to the client for approval", @project.id)
      end

      #UserMailer.new_proposal(@project.user).deliver_now
    else
      format.html { render :new, notice: "Proposal could not be saved" }
      format.json { render json: @proposal.errors, status: :unprocessable_entity }
    end
  end
end

SAVE METHOD IN VUE

saveProposal: function(final) {
    this.$validator.validateAll()

    if (!this.errors.any()) {

        this.saving = true

        if (final == true ) {

            this.proposal.final = true

        } else {

            this.proposal.final = false

        }

        for (var i = 0; i < proposal.milestones_attributes.length; i ++) {

            var ms = proposal.milestones_attributes[i]

            ms.dependencies_attributes = ms.dependencies
            console.log(ms)

        }

        this.$http.post('/projects/' + this.proposal.project_id + '/proposals', {
            proposal: proposal
        })

        .then(function (response) {
            console.log('Saved successfully')
            Turbolinks.visit('/projects/' + this.project.id + '/proposals/${response.body.id}')
        })

        .catch(error => {
            console.log('Error saving proposal. Please correct the errors')
            this.saving = false
        });

** VIEW**

<%= content_tag :div,
  id: "proposal-form",
  data: {
    project: @project.to_json(include: [:industry, :addons, :features, :budget, :type]),
    proposal: @proposal.to_json(except: [:created_at, :updated_at]),
    sections_attributes: @proposal.sections.to_json(except: [:proposal_id, :created_at, :updated_at]),
    cost_items_attributes: @proposal.cost_items.to_json(except: [:proposal_id, :created_at, :updated_at]),
    milestones_attributes: @proposal.milestones.to_json(except: [:proposal_id, :created_at, :updated_at], include: (:dependencies)),
    feedback: @feedback.to_json
  } do %>

<% end %>

PROPOSAL PARAMS

def proposal_params
    params
      .require(:proposal)
      .permit(
        :project_id,
        :supplier_id,
        :version,
        :final,
        :accepted,
        :accepted_at,
        :current,
        billing_phases: [],
        sections_attributes: [
          :id,
          :title,
          :body
        ],
        cost_items_attributes: [
          :id,
          :name,
          :category,
          :timing,
          :price,
          :quantity,
          :taxable,
          :tax,
          :gross,
          :net
        ],
        milestones_attributes: [
          :id,
          :name,
          :due_date,
          :done,
          dependencies_attributes: [
            :id,
            :name,
            :due_date,
            :done
          ]
        ]
      )
      .merge(
        project_id: @project.id,
        supplier_id: @project.supplier_id,
        user_id: @project.user.id,
        version: @version,
        current: true
      )

  end
Reply

Chris:
what is your json look like
it is trying to do a proposal_url but you don’t have a route for it?

Reply

Stephen

Hey @excid3 I’m doing a standard rails show view (not Json’d), but in terms of the JSON parsing, does this help?

Reply

PROPOSAL JSON

var project = JSON.parse(element.dataset.project)
      var proposal = JSON.parse(element.dataset.proposal)
      var sectionsAttributes = JSON.parse(element.dataset.sectionsAttributes)
      var costItemsAttributes = JSON.parse(element.dataset.costItemsAttributes)
      var milestonesAttributes = JSON.parse(element.dataset.milestonesAttributes)
      var feedback = JSON.parse(element.dataset.feedback)

      proposal.sections_attributes = sectionsAttributes
      proposal.cost_items_attributes = costItemsAttributes
      proposal.milestones_attributes = milestonesAttributes

Reply

Chris

you’re submitting the form with Vue-resource / axios
and it wants JSON back
you should see the request in rails say “as JSON”
right?

Reply

Stephen

wait a sec, are you referring to this:
format.json { render :show, status: :created, location: @proposal } in the proposal create action?

Reply

Chris

you should do
format.json { render json: @proposal }

think of it this way
Javascript submits the form to Rails
JS tells it that it wasnt JSON in return
so Rails says okay cool, and calls the format.json block
it needs to render JSON to send back so the Javascript can parse it
and then the JS can redirect using Turbolinks.visit()
you have to include a url of some sort in the JSON back so it can know where to go

one simple thing is to do like
format.json { render json: @proposal, location: @proposal } (edited)
the location will set a url in the HTTP location header you can use to redirect
and still give you the json data of the proposal
but your error from rails said there was no resources :proposals in your routes
so it can’t make that url
you’ll have to fix that or change the url

Reply

Stephen

Ahhh, ok cool. Can you do nested resources with the JSON response? So at the moment, I wanted to redirect to something like /projects/121/proposals/24

Or do I need to create an unnested route for the proposal show action?

Reply

Chris

just pass the url into location
format.json { render json: @proposal, location: [@project, @proposal] } will probably work too

Reply

Chris

I haven’t actually used the location header with vue-resource so you may have to access it some different way
or you can put it into the json
nevermind, looks easy: Turbolinks.visit(response.headers.get('Location'));

Reply

Stephen

Omg, that worked!
Thats brilliant.

Chris you're awesome. I love you man. (his real words / feelings)

Reply

Haha, thats exactly how I felt :) Thanks again @excid3

Reply

LOL this is great. Slack regurgitation to the forum.

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 86,946+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.