Использовать выбранный элемент без выпадающего списка - PullRequest
1 голос
/ 05 февраля 2020

У меня в настоящее время есть страница с ценами на моем веб-сайте, которая использует элементы <select> и <option> html, чтобы позволить пользователям выбирать тарифный план.

Это код для раскрывающегося списка выбора плана:

<select name="plan" class="form-control" id="subscription-plan">
    @foreach ($plans as $key => $plan)
        <option value="{{ $key }}">{{ $plan }}</option>
    @endforeach
</select>

И вот как выглядит форма:

enter image description here

Я хотел бы добавить 2 карты, содержащие информацию о плане он может быть выбран пользователем и действовать так же, как и раскрывающийся список, за исключением того, что он не является раскрывающимся. id="subscription-plan" важен, потому что он отправляет соответствующий план, выбранный пользователем, в Stripe API, который выставляет счет кредитной карте пользователя на сумму, установленную в Stripe. Кто-нибудь знает, как мне этого добиться?

Я бы хотел сделать что-то подобное (но без выпадающего стиля):

<select name="plan" class="form-control" id="subscription-plan">
                @foreach ($plans as $key => $plan)
                    <option value="{{ $key }}">
                        <div class="card mb-5 mb-lg-0">
                            <div class="card-body">
                                <h5 class="card-title text-muted text-uppercase text-center">Monthly</h5>
                                <h6 class="card-price text-center">$8.44<span class="period">/month</span></h6>
                            </div>
                        </div>
                    </option>
                @endforeach
            </select>

ОБНОВЛЕНИЕ: У меня есть попробовал это:

@foreach ($plans as $key => $plan)
        <div class="col-6">
            <label>
                <input type="radio" name="plan" value="{{ $key }}" class="card-input-element" id="subscription-plan">

                <div class="panel panel-default card-input">
                    <div class="panel-heading">{{ $plan }}</div>
                    <div class="panel-body">2 Memorials</div>
                </div>
            </label>
        </div>
    @endforeach

Этот код работает и дает мне желаемый эффект наличия выбираемых карт, но теперь Stripe API получает только «ежемесячный» план, даже если пользователь отправляет данные своей кредитной карты после выбора «годовой» план. Это потому, что теперь оба входа имеют id="subscription-plan". enter image description here

Полоса JavaScript:

        const stripe = Stripe('{{ env('STRIPE_KEY') }}');
        const elements = stripe.elements();
        const cardElement = elements.create('card');
        cardElement.mount('#card-element');
        const cardHolderName = document.getElementById('card-holder-name');
        const cardButton = document.getElementById('card-button');
        const clientSecret = cardButton.dataset.secret;
        const plan = document.getElementById('subscription-plan').value;

        cardButton.addEventListener('click', async (e) => {
            const { setupIntent, error } = await stripe.handleCardSetup(
                clientSecret, cardElement, {
                    payment_method_data: {
                        billing_details: { name: cardHolderName.value }
                    }
                }
            );
            if (error) {
                // Display "error.message" to the user...
            } else {
                // The card has been verified successfully...
                console.log('handling success', setupIntent.payment_method);

                axios.post('subscribe',{
                    payment_method: setupIntent.payment_method,
                    plan : plan
                }).then((data)=>{
                    location.replace(data.data.success_url)
                });
            }
        });

ОБНОВЛЕНИЕ 2: Я заменил const plan = document.getElementById('subscription-plan').value; на var plan = document.querySelector('input[name="plan"]:checked').value;. Теперь я получаю Uncaught TypeError: Cannot read property 'value' of null в консоли при попытке отправки.

Ответы [ 3 ]

1 голос
/ 05 февраля 2020

Это должно быть выполнимо, просто перебирая планы создания карт и не используя select вообще. Вы можете обратиться к выбору карты с помощью обработчиков onclick или обработав карты как переключатели вроде того, что вы видите здесь: https://codepen.io/stefanzweifel/pen/RNvGwz

Тогда вместо использования значения select вы использовал значение радио.

0 голосов
/ 09 февраля 2020

Я решил JavaScript сторону этого вопроса самостоятельно. Я изменил var plan = document.querySelector('input[name="plan"]:checked').value; на var plan;. Затем я добавил: $('input:radio').on('click', function(e) { plan = this.value; });.

Теперь форма правильно отправляет правильный план на основе опции, выбранной пользователем для Stripe API. Для меня было удивительно трудной задачей заставить эту форму работать без использования элементов <select> и <option>. Вот готовый рабочий код:

HTML

<div class="col-6">
        <label>
            <input type="radio" name="plan" value="monthly" class="card-input-element" checked="checked">

            <div class="panel panel-default card-input">
                <div class="panel-heading">Monthly</div>
            </div>
        </label>
    </div>
    <div class="col-6">
        <label>
            <input type="radio" name="plan" value="yearly" class="card-input-element">

            <div class="panel panel-default card-input">
                <div class="panel-heading">Yearly</div>
            </div>
        </label>
    </div>

JavaScript

<script src="{{ asset('js/jquery-3.4.1.min.js') }}"></script>
<script>
    window.addEventListener('load', function() {
        const stripe = Stripe('{{ env('STRIPE_KEY') }}');
        const elements = stripe.elements();
        const cardElement = elements.create('card');
        cardElement.mount('#card-element');
        const cardHolderName = document.getElementById('card-holder-name');
        const cardButton = document.getElementById('card-button');
        const clientSecret = cardButton.dataset.secret;
        var plan;
        $('input:radio').on('click', function(e) {
            plan = this.value;
        });

        cardButton.addEventListener('click', async (e) => {
            const { setupIntent, error } = await stripe.handleCardSetup(
                clientSecret, cardElement, {
                    payment_method_data: {
                        billing_details: { name: cardHolderName.value }
                    }
                }
            );
            if (error) {
                // Display "error.message" to the user...
            } else {
                // The card has been verified successfully...
                console.log('handling success', setupIntent.payment_method);

                axios.post('subscribe',{
                    payment_method: setupIntent.payment_method,
                    plan : plan
                }).then((data)=>{
                    location.replace(data.data.success_url)
                });
            }
        });
    });
</script>

Подробнее опытные программисты, возможно, знали, как достичь этого с самого начала, но я думаю, что мы все должны как-то научиться. Спасибо всем за помощь.

0 голосов
/ 05 февраля 2020

Вы можете просто использовать атрибут size для select

<select name="plan" class="form-control" size=3 id="subscription-plan">
  <option value="1">
    <div class="card mb-5 mb-lg-0">
      <div class="card-body">
        <h5 class="card-title text-muted text-uppercase text-center">Monthly</h5>
        <h6 class="card-price text-center">$8.44<span class="period">/month</span></h6>
      </div>
    </div>
  </option>

  <option value="2">
    <div class="card mb-5 mb-lg-0">
      <div class="card-body">
        <h5 class="card-title text-muted text-uppercase text-center">Daily</h5>
        <h6 class="card-price text-center">$0.44<span class="period">/day</span></h6>
      </div>
    </div>
  </option>
  <option value="3">
    <div class="card mb-5 mb-lg-0">
      <div class="card-body">
        <h5 class="card-title text-muted text-uppercase text-center">Yearly</h5>
        <h6 class="card-price text-center">$80.44<span class="period">/year</span></h6>
      </div>
    </div>
  </option>
</select>
...