[SOLVED] How to refresh just my page-content?

I have a view that includes top nav, a scrollable tab list of TOPICS, a scrollable list of Offers representing the selected topic and finally my bottom nav with icons for each view. The scrollable tab list of TOPICS currently calls a route with the topic as a parameter. This results in the entire Offers view being re-rendered including the top-nav, the scrollable tabs and the scrollable list of Offers.

How can I structure this offers view so that only the page-content gets refreshed when you select one of the scrollable topics?

Here is a simplified version of the Offers view:

<template>
  <div class="page" data-name="offers">
    <div class="navbar">
      <div class="navbar-inner">
        <div class="left">
          <div class="title">
            <i class="icon material-icons" style="display:inline;vertical-align:middle;">whatshot</i>
            <div style="display:inline;vertical-align:middle;font-size:24px;margin-left:-5px;">brighter</div>
          </div>
        </div>
        <div class="right">
          <div class="searchbar searchbar-inline" style="width:200px">
            <div class="searchbar-input-wrap">
              <input type="search" placeholder="Search">
              <i class="searchbar-icon"></i>
              <span class="input-clear-button"></span>
            </div>
          </div>
          <div id="avatar-out">
              <a href="#" class="link icon-only panel-open" style="margin-right:5px;" data-panel="right">
                <i class="icon f7-icons ios-only" style="font-size:40px">person_round_fill</i>
                <i class="material-icons md-only" style="font-size:40px">account_circle</i>
              </a>
          </div>
          <div hidden id="avatar-in">
              <a href="#" class="link icon-only panel-open" style="margin-right:5px;" data-panel="right">
                <img id="user-pic" src="" style="width:40px;height:40px;border-radius:20px;">
              </a>
          </div>
        </div>
      </div>
    </div>

    <!-- Scrollable nav for categories -->
    <div class="toolbar tabbar tabbar-scrollable toolbar-top">
      <div class="toolbar-inner">
        <!-- Links have "tab-link" class instead of just "link" to switch tabs -->
        <a href="/offers/ALL/" class="tab-link tab-link-active">ALL</a>
        <a href="/offers/TOPICONE/" class="tab-link">TOPICONE</a>
        <a href="/offers/TOPICTWO/" class="tab-link">TOPICTWO</a>
        <a href="/offers/TOPICTHREE/" class="tab-link">TOPICTHREE</a>
      </div>
    </div>
    <div class="page-content">
      {{#each offers}}
      <div class="card offer-card" id="{{this.id}}">
        <div class="card-header">
          <div>
          <div class="offer-avatar"><img src="{{this.pic}}" class="avatar-image"/></div>
          <div class="offer-name">{{this.name}}
            <a style="float:right" class="link popover-open" href="#" data-popover=".popover-links"><i class="icon f7-icons ios-only">more_fill</i>
                  <i class="material-icons md-only">more_horiz</i></a>
          </div>
          </div>
        </div>
        <div class="card-content card-content-padding">
          <p>{{this.offer}}</p>
          <div class="card">
            <div class="card-content">
            </div>
          </div>
        </div>
      </div>
      {{/each}}
    </div>
  </div>
</template>
<script>
  return {
    data() {
      return {
        offers: [],
      };
    },
    mounted() {
      const self = this;
      self.getItems();
    },
    methods: {
      async getItems() {
        // load items from DB and set state for the page
      }
    }
  }
</script>

Any guidance on the above?

Currently I use authStateObserver which finds the user avatar in the top navbar (one on each page) and updates it with the logged in users avatar. When I attempt to do this when my offer page refreshes the top nav bar elements do not refresh. Is the VDOM already merged with the DOM when pageAfterIn as I think?

I know the correct way to do this is likely to be separating the top nav completely and using the same on my Offers and Chats pages. Then separating the scrollable tabs on my Offers page so that it just refreshed the list of Offers with each selection. I am puzzled how to do this in F7 after reading a ton of example posts.

    on: {
  pageAfterIn: function (e, page) {
    console.log('page after reinit');
    if (isUserSignedIn()) {
        authStateObserver(getUser());
    }
  },
},

If you need to change content when you click on toolbar links, then your logic should be the following:

  • remove href from those links
  • assign some method with on @click for those links
  • add this method to component
  • request new offers based on clicked link and update DOM with $setState
1 Like

Brilliant! It took me a minute to find a reference to @click and calling a method function but then it was an easy conversion.

<a @click="getItems('TOPICTWO')" class="tab-link">TOPICTWO</a>

One additional aspect of this … how do you then highlight the tab that was selected? Its not doing that automatically when I use the @click

Because these are not actually tabs they won’t add class. Add tab-link-active using same template conditions:

<a class="tab-link {{#js_if 'this.activeTab === "ALL"'}}tab-link-active{{/js_if}}">...
<a class="tab-link {{#js_if 'this.activeTab === "TOPICONE"'}}tab-link-active{{/js_if}}">...

You should also add that activeTab to component data and change it whithin link click handler

I did the following and it works!

     <a @click="getItems('CAREER')" class="tab-link {{#js_if 'this.activeTab === "CAREER"'}}tab-link-active{{/js_if}}">CAREER</a>

I initialize an activeTab context variable like so:

data() {
  return {
    offers: [],
    activeTab: 'ALL',
  };
},

And in my getItems I call setState like so:

    this.$setState({ offers: offerList, activeTab: topic })

I had to change a previous setting of activeTab that was confusing the code but once I did that the setting worked perfectly.

Thank you.

There is one remaining issue.

The active tab used be highlighted with an underline below the label. When I select another tab the label highlights but the underline does not move.

Also, on a different page I have a similar set of tabs and on that one the initial active setting doesnt have an underline at all. (see images)

Yea, this is because MD theme requires extra JS to handle that line/border. You need to call:

app.toolbar.setHighlight(tabbarEl);

after you have changed tab-link-active classes. toolbarEl is the CSS selector of containing toolbar

That works!

I put the setHighlight call just after the $setState. Does that create a race condition on whether the DOM gets updated with the new active tab before? Or does $setState do all its rendering synchronously before returning?

$setState does rendering in sync, so calling setHighlight after $setState is fine

1 Like