schnacks
schnacks

Reputation: 1

Show data-attributes from selected Radio-Button with knockout js

I am really new to knockoutjs and find it kind of hard to work with it. Things that were very easy for me with jQuery, don't work at all with knockout...

On a Magento 2 Shop I want to display summarized data from the selected shipping method. The "checked" binding is already in use for Magento setting the shipping method to the quote. Now I have some custom data at my input elements (eg. Shipping Name, Shipping Timerange etc.) which I want to display in a "Summarize" Box

it should look like this

<div id="selected-method-summary">
    <span class="method-name" data-bind="text: selectedMethod.name"></span>
    <span class="method-timerange" data-bind="text: selectedMethod.timerange"></span>
    <span class="method-price" data-bind="text: selectedMethod.price"></span>
</div>

<fieldset class="fieldset rate" data-bind="visible: (rates().length > 0)">
    <dl class="items methods" data-bind="foreach: shippingRateGroups, mageInit: {'accordion':{'openedState': 'active', 'collapsible': true, 'active': [2], 'multipleCollapsible': true}} ">
        <div class="method-group" attr="'id': $data" data-role="collapsible">
            <dt class="item-title" data-role="title"><span data-bind="text: $data"></span> <span class="accordion-toggle"></span></dt>
            <dd class="item-options" data-role="content" attr="'id': $data + 'content'" data-bind="foreach: { data:$parent.getRatesForGroup($data), as: 'method' }">
                <div click="element.selectShippingMethod" attr="'data-date': method.extension_attributes.date, 'data-timerange': method.extension_attributes.time_range" data-bind="css: {'field choice item': available, 'message error': !available} ">
                    <!-- ko ifnot: (available) -->
                    <div data-bind="text: error_message"></div>
                    <!-- /ko -->
                    <!-- ko if: (available) -->
                    <input type="radio"
                            class="radio"
                            data-bind="
                click: $parents[1].selectShippingMethod,
                checked: element.isSelected,
                attr: {
                        value: carrier_code + '_' + method_code,
                        id: 's_method_' + carrier_code + '_' + method_code
                        }
                "/>
                    <label class="label" data-bind="attr: {for: 's_method_' + carrier_code + '_' + method_code}">
                        <!-- ko text: $data.method_title --><!-- /ko -->
                        <each args="element.getRegion('price')" render="" />
                    </label>
                    <!-- /ko -->
                </div>
            </dd>
        </div>
    </dl>
</fieldset>

and then I want that the data inside the summary block change depending on the method which is selected. the "data-bind="checked: element.isSelected" only gives one value back

isSelected: ko.computed(function () {
            return quote.shippingMethod() ?
                quote.shippingMethod()['carrier_code'] + '_' + quote.shippingMethod()['method_code'] :
                null;
        }),

I've tried to extend this "isSelected" method, but I don't know how to do that without destroying magento functionality

how can I realize that?

thank you in advance

Upvotes: 0

Views: 553

Answers (1)

Aleksej Vasinov
Aleksej Vasinov

Reputation: 2797

You need to change your mindset when using KO :) You need to have everything in your ViewModel class. Here is simple example which list all payment methods and display summary.

P.S. You need to play a bit with radio checked attribute :)

// Model for payments
class PaymentMethod {
  constructor(id, name, price) {
    this.id = id;
    this.name = name;
    this.price = price;
  }
}

class AppViewModel {
  constructor() {
    // Add payments to display them
    this.paymentMethods = [
      new PaymentMethod(1, "First", 100),
      new PaymentMethod(2, "Second", 200),
      new PaymentMethod(3, "Third", 300),
    ];
    
    // No selected payment method
    this.selectedMethod = ko.observable(new PaymentMethod(0, "", 0));
  }
  
  onPaymentClicked = (method) => {
    this.selectedMethod(method);
  }
}

ko.applyBindings(new AppViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind="visible: selectedMethod().id != 0">
    <span class="method-name" data-bind="text: selectedMethod().name"></span>
    <span class="method-price" data-bind="text: selectedMethod().price"></span>
</div>

<div data-bind="foreach: paymentMethods">
  <input type="radio" name="paymentGroup" data-bind="click: $root.onPaymentClicked"> <span data-bind="text: name"></span><br />
</div>

Upvotes: 0

Related Questions