LoginSignup
0
2

More than 1 year has passed since last update.

[JavaScript]今日のエラー(解決済)

Last updated at Posted at 2021-08-13

はじめに

本記事では、クレジットカード機能を実装するため、
JavaScriptファイルでコードを記述していますが、
コンソール上でエラーが発生しています。
完全に自分本位な記事で恐縮ですが、備忘録として、ここに残します。

エラー内容

商品購入をするページ(index.html.erb)に遷移後、
createアクションで購入しようとするも、

Uncaught TypeError: Cannot read property 'removeAttribute' of null
    at Object.<anonymous> (card.js:26)
    at (index):1

というエラーが出てしまう。
空の'removeAttribute'のプロパティは読めない。
直訳したらそう怒っているように思う。

コード

card.js
const pay = () => {
  Payjp.setPublicKey("pk_test_4e8ca7835559d124aa4f5cf7");
  const submit = document.getElementById("button");
  submit.addEventListener("click", (e) => {
    e.preventDefault();

    const formResult = document.getElementById("charge-form");
    const formData = new FormData(formResult);

    const card = {
      number: formData.get("order_form[number]"),
      exp_month: formData.get("order_form[exp_month]"),
      exp_year: `20${formData.get("order_form[exp_year]")}`,
      cvc: formData.get("order_form[cvc]"),
    };
    console.log(card);

    Payjp.createToken(card, (status, response) => {
      if (status == 200) {
        const token = response.id;
        const renderDom = document.getElementById("charge-form");
        const tokenObj = `<input value=${token} name='token' type="hidden">`;
        renderDom.insertAdjacentHTML("beforeend", tokenObj);
      }

      document.getElementById("card_number").removeAttribute("name");
      document.getElementById("card-exp-month").removeAttribute("name");
      document.getElementById("card-exp-year").removeAttribute("name");
      document.getElementById("card-cvc").removeAttribute("name");

      document.getElementById("charge-form").submit();
    });
  });
};

window.addEventListener("load", pay);
purchase_controller.rb
class PurchasesController < ApplicationController

  def index
    @item = Item.find(params[:item_id])
    @order_form = OrderForm.new
  end

  def create
    @item = Item.find(params[:item_id])
    @order_form = OrderForm.new(order_params)
    if @order_form.valid?
      pay_item
      @order_form.save
      redirect_to root_path
    else
      render :index
    end
  end

  private

  def order_params
    params.require(:order_form).permit(:postal_code, :prefecture_id, :city, :address, :telephone, :building).merge(user_id: current_user.id, item_id: @item.id, token: params[:token])
  end

  def pay_item
    Payjp.api_key = "sk_test_91d4dc8c4053b019ff2f024c"
    Payjp::Charge.create(
      amount: @item[:price],
      card: order_params[:token],
      currency: 'jpy'
    )
  end
end
<%= render "shared/second-header"%>

<div class='transaction-contents'>
  <div class='transaction-main'>
    <h1 class='transaction-title-text'>
      購入内容の確認
    </h1>
    <%# 購入内容の表示 %>
    <div class='buy-item-info'>
      <%= image_tag @item.image, class: 'buy-item-img' %>
      <div class='buy-item-right-content'>
        <h2 class='buy-item-text'>
          <%= @item.item_name %>
        </h2>
        <div class='buy-item-price'>
          <p class='item-price-text'>¥<%= @item.price %></p>
          <p class='item-price-sub-text'><%= @item.claim.name %></p>
        </div>
      </div>
    </div>
    <%# /購入内容の表示 %>

    <%# 支払額の表示 %>
    <div class='item-payment'>
      <h1 class='item-payment-title'>
        支払金額
      </h1>
      <p class='item-payment-price'>
        ¥<%= @item.price %>
      </p>
    </div>
    <%# /支払額の表示 %>

    <%= form_with id: 'charge-form',url: item_purchases_path(@item) ,model: @order_form ,class: 'transaction-form-wrap',local: true do |f| %>
    <%= render 'shared/error_messages', model: f.object %>

    <%# カード情報の入力 %>
    <div class='credit-card-form'>
      <h1 class='info-input-haedline'>
        クレジットカード情報入力
      </h1>
      <div class="form-group">
        <div class='form-text-wrap'>
          <label class="form-text">カード情報</label>
          <span class="indispensable">必須</span>
        </div>
        <%= f.text_field :number, class:"input-default", id:"card-number", placeholder:"カード番号(半角英数字)", maxlength:"16" %>
        <div class='available-card'>
          <%= image_tag 'card-visa.gif', class: 'card-logo'%>
          <%= image_tag 'card-mastercard.gif', class: 'card-logo'%>
          <%= image_tag 'card-jcb.gif', class: 'card-logo'%>
          <%= image_tag 'card-amex.gif', class: 'card-logo'%>
        </div>
      </div>
      <div class="form-group">
        <div class='form-text-wrap'>
          <label class="form-text">有効期限</label>
          <span class="indispensable">必須</span>
        </div>
        <div class='input-expiration-date-wrap'>
          <%= f.text_area :exp_month, class:"input-expiration-date", id:"card-exp-month", placeholder:"例)3" %>
          <p></p>
          <%= f.text_area :exp_year, class:"input-expiration-date", id:"card-exp-year", placeholder:"例)23" %>
          <p></p>
        </div>
      </div>
      <div class="form-group">
        <div class='form-text-wrap'>
          <label class="form-text">セキュリティコード</label>
          <span class="indispensable">必須</span>
        </div>
        <%= f.text_field :cvc, class:"input-default", id:"card-cvc", placeholder:"カード背面4桁もしくは3桁の番号", maxlength:"4" %>
      </div>
    </div>
    <%# /カード情報の入力 %>

    <%# 配送先の入力 %>
    <div class='shipping-address-form'>
      <h1 class='info-input-haedline'>
        配送先入力
      </h1>
      <div class="form-group">
        <div class='form-text-wrap'>
          <label class="form-text">郵便番号</label>
          <span class="indispensable">必須</span>
        </div>
        <%= f.text_field :postal_code, class:"input-default", id:"postal-code", placeholder:"例)123-4567", maxlength:"8" %>
      </div>
      <div class="form-group">
        <div class='form-text-wrap'>
          <label class="form-text">都道府県</label>
          <span class="indispensable">必須</span>
        </div>
        <%= f.collection_select(:prefecture_id, Prefecture.all, :id, :name, {}, {class:"select-box", id:"prefecture"}) %>
      </div>
      <div class="form-group">
        <div class='form-text-wrap'>
          <label class="form-text">市区町村</label>
          <span class="indispensable">必須</span>
        </div>
        <%= f.text_field :city, class:"input-default", id:"city", placeholder:"例)横浜市緑区"%>
      </div>
      <div class="form-group">
        <div class='form-text-wrap'>
          <label class="form-text">番地</label>
          <span class="indispensable">必須</span>
        </div>
        <%= f.text_field :address, class:"input-default", id:"addresses", placeholder:"例)青山1-1-1"%>
      </div>
      <div class="form-group">
        <div class='form-text-wrap'>
          <label class="form-text">建物名</label>
          <span class="form-any">任意</span>
        </div>
        <%= f.text_field :building, class:"input-default", id:"building", placeholder:"例)柳ビル103"%>
      </div>
      <div class="form-group">
        <div class='form-text-wrap'>
          <label class="form-text">電話番号</label>
          <span class="indispensable">必須</span>
        </div>
        <%= f.text_field :telephone, class:"input-default", id:"phone-number", placeholder:"例)09012345678",maxlength:"11"%>
      </div>
    </div>
    <%# /配送先の入力 %>
    <div class='buy-btn'>
      <%= f.submit "購入" ,class:"buy-red-btn", id:"button" %>
    </div>
    <% end %>
  </div>
</div>
<%= render "shared/second-footer"%>

仮説

空の'removeAttribute'のプロパティは読めない。なら、removeAttributeを消してしまおうか。

②送信したデータが保存されていない。ということは、コントローラーのcreateアクションの記載に誤りがある?

③モデルで各カラムたちの記述を正確にできていない?「_id」の有無。_なのか.なのか。

④ビューは画面が正確に遷移できている状態であるため、除外。ルーティングについても、問題視されておらずエラー内容を見る限り関係ないため、除外。

明日のアクション

仮説に則り、実行していく。

終わりに

未解決のため、「終わりに」ではないですが、
解決した際には、またここの記事に報告をするかと思います。

明日も楽しんでプログラミング、やっていきます!!

追記

解決しました!
内容は絶望するものでした。

document.getElementById("card_number").removeAttribute("name");
document.getElementById("card-exp-month").removeAttribute("name");
document.getElementById("card-exp-year").removeAttribute("name");
document.getElementById("card-cvc").removeAttribute("name");

card_numberではない・・・
card-numberだ・・・。

これだけです。。。
時に、コピペした方が良いこともあるのだなと、感じました。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2