0

how to implement below jQuery code into knockout js, Actually I'm trying to call this function on a button click event using knockout js, but it's not working

HTML code:

<div>
    <ul class="list-group">
       <li>
        <button id="buttonid">click</button>
        Item 1
       </li>
        <li>
        <button id="buttonid">click</button>
        Item 2
       </li>
    </ul>
</div>

jQuery COde:

$('#buttonid').on("click",".list-group-item",function(e){
console.log($(this).text());
console.log(e.target.id);
});

In this code .list-group-item is the class of ul tag. Here I wanna try to get title text of li items.

please guide me to implement above jQuery function in knockout js!

2 Answers 2

5

Template

  • Removed id's since there shouldn't be more than one element on page with the same id
  • Wrapped list item text with a span since trying to output the text of the li element would also output the button text

With Magento Init Script

<div>
    <ul class="list-group" data-role="item-announcer">
        <li>
            <button data-action="announce-item">click</button>
            <span data-role="item">Item 1</span>
        </li>
        <li>
            <button data-action="announce-item">click</button>
            <span data-role="item">Item 2</span>
        </li>
    </ul>
</div>

<script type="text/x-magento-init">
    {
        "[data-role=item-announcer]": {
            "Magento_Theme/js/item-announcer": {}
        }
    }
</script>

With Data Mage Init Attribute

<div>
    <ul class="list-group" data-mage-init='{"Magento_Theme/js/item-announcer": {}}'>
        <li>
            <button data-action="announce-item">click</button>
            <span data-role="item">Item 1</span>
        </li>
        <li>
            <button data-action="announce-item">click</button>
            <span data-role="item">Item 2</span>
        </li>
    </ul>
</div>

Component

In app/design/frontend/[vendor]/[theme]/Magento_Theme/web/js/item-announcer.js:

define([
    'jquery',
    'domReady!'
], function($) {
    return function(config, element) {
        let actionSelector = '[data-action=announce-item]';
        let itemSelector = '[data-role=item]';

        $(element).on('click', actionSelector, function (e) {
            e.preventDefault();
            let item = $(this).siblings(itemSelector);
            console.log(item.text());
        });
    }
});

With Knockout Component

Template

<?php
/** @var \Magento\Framework\View\Element\Template $block */
$jsId = $block->getJsId();
$items = [
    [
        'name' => 'Item 1'
    ],
    [
        'name' => 'Item 2'
    ]
];
?>

<div data-bind="scope: 'item-announcer-<?= $jsId; ?>'">
    <ul class="list-group" data-bind="visible: isVisible()" style="display: none;">
        <!-- ko foreach: items -->
        <li>
            <button data-bind="click: $parent.announce">click</button>
            <span data-bind="text: name"></span>
        </li>
        <!-- /ko -->
    </ul>
</div>

<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "item-announcer-<?= $jsId; ?>": {
                        "component": "Magento_Theme/js/item-announcer",
                        "items": <?= json_encode($items); ?>
                    }
                }
            }
        }
    }
</script>

Component

In app/design/frontend/[vendor]/[theme]/Magento_Theme/web/js/item-announcer.js:

define([
    'uiComponent'
], function(Component) {
    return Component.extend({
        defaults: {
            items: []
        },

        /**
         * @inheritdoc
         */
        initObservable: function () {
            this._super()
                .observe('items');
            return this;
        },

        /**
         * Announce Text
         *
         * @param item
         */
        announce: function (item) {
            console.log(item.name);
        },

        /**
         * Get whether component is visible
         *
         * @returns {boolean}
         */
        isVisible: function () {
            return this.items().length > 0;
        }
    });
});
1
  • Thanks for your effort Man! Aug 5, 2020 at 15:59
1

If you want to implement the jquery click event that you can refer the document as sometime knockout component call after the dom render you can use the below document jquery selector for the click event.

jQuery(document).on('click', '#your_selector', function (event) {
       console.log("element click");
}

Also in the html file you can use the data-bind click event as below and add name of your component js function.

<button data-bind="attr: {title: $t('your title')}, click: function_name" id="selector_id" class="button action primary" type="button">
        <span data-bind="i18n: ButtonText"></span>
</button>
1
  • Thanks brother! I also got some help from your solution. Aug 7, 2020 at 7:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.