J
J
JastaFly2021-05-13 15:50:36
1C-Bitrix
JastaFly, 2021-05-13 15:50:36

Composite site and $frame->beginStub()?

Good day to all! There is a site on Bitrix with composite site technology enabled . The authorization button did not work on the site, when clicked on it, a modal with a form for login and password is called, just at some point an eventListener began to fly from it. In the course of digging into the problem, I found out the problem in the composite, and if it is cut off, then everything works fine. The button code looks like this:

<?
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true)
    die();

use Bitrix\Main\Localization\Loc;
use Citfact\SiteCore\EventAlert\EventAlertManager;

$frame = new \Bitrix\Main\Page\FrameBuffered('authorize_'.ToLower($arParams['ID']));
$frame->begin();
$cUser = new \CUser();
if ($cUser->IsAuthorized()) {

    $userId = (int)$cUser->GetID();

    // Счетчик оповещений о событиях
    $alertManager = new EventAlertManager($userId);
    $allAlertsCnt = $alertManager->getAllAlertsCnt();
    ?>
    <div class="header__link header__link--auth header__lk"
        <?= ((int)$allAlertsCnt > 0 ) ? 'not_empty' : 'empty'; ?>
         data-alerts-num-wrap>
        <svg class='i-icon header-nav__link'>
            <use xlink:href='#icon-personal'></use>
        </svg>
        <span data-alerts-num><?= $allAlertsCnt; ?></span>
        <div class="header-nav__down">
            <ul class="header-nav__down-list">
                <li>
                    <a href="<?= SITE_DIR; ?>account">
                        <?= Loc::getMessage('HEADER_PERSONAL_AREA'); ?>
                    </a>
                </li>
                <li>
                    <a href="<?= SITE_DIR; ?>?logout=yes">
                        <?= Loc::getMessage('HEADER_EXIT'); ?>
                    </a>
                </li>
            </ul>
        </div>
    </div>
<? } else { ?>
    <div class="header__link header__link--right">
        <a data-href="/local/include/modals/auth.php?site=<?= SITE_ID; ?>" class="header__link header__link--auth" data-modal="ajax">
            <svg class='i-icon'>
                <use xlink:href='#icon-personal'></use>
            </svg>
        </a>
        <a data-href="/local/include/modals/auth.php?site=<?= SITE_ID; ?>" class="header__link header__link--auth header__link__button" data-modal="ajax"><?= Loc::getMessage('CITFACT_TEMPLATE_SUBSCRIBE_BUTTON'); ?></a>
    </div>
<? } ?>
<? $frame->beginStub(); ?>
    <a data-href="/local/include/modals/auth.php?site=<?= SITE_ID; ?>" class="header__link header__link--auth" data-modal="ajax">
        <svg class='i-icon'>
            <use xlink:href='#icon-personal'></use>
        </svg>
    </a>
<? $frame->end(); ?>

So if you remove $frame->beginStub() then the button starts working. Pliz tell me what is the reason?!?? I just didn't fully understand how the composite works?!??
Thank you all in advance)

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
Roman Gritsuk, 2021-05-13
@JastaFly

To understand the problem, you need to understand how the composite works.
This is how dynamic content is marked up and its stub inside the component template:

$frame = new \Bitrix\Main\Page\FrameBuffered("my_dynamic"); 
$frame->begin();
  // Содержание динамической области
$frame->beginStub();
  // Заглушка
$frame->end();

When the page is initially loaded, the browser receives HTML that lacks dynamic content. In its place are stubs.
After loading the page, you run a JS script that attaches a handler to your button. But your button is a stub.
After that, Bitrix itself loads dynamic content in place of the stub. In the DOM model, this will be another button and will not have your handler on it.
Therefore, you need to either initialize the handler from the dynamic area, or initially hang up the event not on the button itself. For example in jQuery it can be done like this
$(document).on('click', '.header__link.header__link--auth', callback);

A
Alexander, 2021-05-13
Madzhugin @Suntechnic

Wang that the problem is not at all in the composite, but in the js listeners that are traditionally hung on the page readiness event.
As a result, the static part cached by the composite is loaded first, then the scripts are triggered. Then the block with the button is loaded. But since the scripts have already worked when the button was not there, then no listener was hooked on it. And when the button appeared on the page, the train with the listeners had long since left.
js should not rely on the readiness of a DOM that is not created by itself, as jQuery has taught many people over the years to do.
If events are assigned to DOM elements, this should be done by whoever creates the html. If, in this case, html is created on the server using PHP, then let events be assigned on the server directly in this html.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question