Ad

OctoberCMS Javascript API AJAX Call To A Component Function To Update Component's Partial

- 1 answer

So I have the following file structure:

plugins/myname/pluginname/components/pluginname/default.htm
plugins/myname/pluginname/components/PluginName.php

default.htm acts as the partial of the component. and I have the following JS API

setInterval(function(){
    $.request('onEverySecond', {
        update: {'@default.htm':'#rate-marquee'},
        complete: function() {
            console.log('Finished!');
        }
    })
}, 1000);

onEverySecond is a function in PluginName.php that updates a variable called fx thrown to default.htm.

At the front end the partial default.htm seems to be updated, but it refreshes the whole partial which is not what I want, it causes the marquee to replay again and again and only be able to show the first few piece of contents. All I wanted is that the AJAX will update only the variable fx where the data is updated.

How can I achieve that?

EDIT 1:

Here is the partial markup:

{% set fx = __SELF__.fx %}
<marquee id="rate-marquee" name="rate-marquee" onmouseover="this.stop();" onmouseout="this.start();">
    <ul>
        {% for item in fx %}
            <li>
            {{ item.Item | trim('u')}}: {{ item.BID }} {% if item.Revalue == 0 %} <div class="arrow-up"></div> {% else %} <div class="arrow-down"></div> {% endif %}
            </li>
        {% endfor %}
    </ul>
</marquee>

Additionally, here is the code in PluginName.php

public function onRun()
{
    $this->addJs('/plugins/SoyeggWebDevelopment/fxmarquee/assets/js/default.js');
    $this->updateFX();
}


public function onEverySecond()
{
    $this->updateFX();
}

public $fx;

So updateFX() works perfectly well too.

Ad

Answer

Here problem seems you are replacing whole marquee it causes to re-render it.

To solve this we can just update portion inside marquee

setInterval(function(){
    $.request('onEverySecond', {        
        complete: function() {
            console.log('Finished!');
        }
    })
}, 1000);

We don't do anything special here just a simple ajax call

to update portion of marquee we need to assign id to it and we define internal partial

<marquee id="rate-marquee" 
         name="rate-marquee" 
         onmouseover="this.stop();" onmouseout="this.start();">
    <ul id='rate-marquee-inner'> <!-- <= here -->
      {% partial __SELF__ ~ '::_marquee_inner' %}        
    </ul>
</marquee>

_marquee_inner.htm partila markup

{% set fx = __SELF__.fx %}
{% for item in fx %}
    <li>
    {{ item.Item | trim('u')}}: {{ item.BID }} {% if item.Revalue == 0 %} <div class="arrow-up"></div> {% else %} <div class="arrow-down"></div> {% endif %}
    </li>
{% endfor %}

and to update that portion we just need to return markup array

function onEverySecond() {
    $this->updateFX();
    return ['#rate-marquee-inner' => $this->renderPartial('_marquee_inner.htm')];
}

this will just push new updated markup to given id #rate-marquee-inner so now it will just update inner portion of marquee and marquee will not re-render.

if any doubt please comment.

Ad
source: stackoverflow.com
Ad