Ajax request on "data" or on "page.init"?

What is the best/right way to make a ajax-request within a router-component?
Within the “data”-method or on one of the “pageEvents” (which one)?

...
data: function () { return fetch(ajax).then(..); };

on: { 
pageMounted: function (e, page) { return fetch(ajax).then(..);; }, 
pageInit: function (e, page) { return fetch(ajax).then(..);}, 
pageBeforeIn: function (e, page) { return fetch(ajax).then(..);},

The “data”-method makes request every time when data is called, or?

data-method is called every time when app/component installed.

And fetch() is an async function, it doesn’t return data, it returns promise object
so

won’t work any way

yes my fetch method works I only cut the return.

The question was, were to put the ajax-method?

data-method is called every time when app/component installed.

installed? really? So when app component is “installed”, then “pageInit” is also called every time when app comp is installed.

data called in the beginning of component creation, before all lifecycle hooks and page events, so you can use data in them.

The safest place to do xhr request will be on mounted hook or on pageMounted/Init events to make sure the component element successfully mounted to DOM

The only issue is that what you have in component <template> won’t wait for your request and will be rendered with initial data provided. So if you do ajax request in page then you’ll have to manually update related HTML.

Another way of doing it is using async route:

{
  path: '/some-page/',
  async(routeTo, routeFrom, resolve, reject) {
    fetch(ajax)
      .then(response => response.json())
      .then((data) => {
        // resolve route with componentUrl and requested context
        resolve(
          {
            componentUrl: 'some-component.html'
          },
          // pass context
          {
            context: response.json()
          }
        );
      });
  }
}
1 Like

Wow. So the best place in my case in doing ajax-request is using “async()”-method - the others are not usable in my case: Because before page is rendered, it must request data from the server and put these requested data within the page template.

Thanks!

On question:

When I have this:

{
		    name: "page1",
		    path: "/page1/",
		    component: page1,
		  },

And within js-component “page1”, I have “render()”, “data()”-methods.

So the render()-method is always called AFTER the **data()-**method. Right?

How to handle such things?:

  render() {
    // context
    const self = this;
    const data = this.$root;
    
    console.log(self);
    console.log("data from xhr:");
    console.log(data); // result: undefined
   
    return ..
  },
  
  data() {
      console.log("request data..");
      return this.$app.request.json("...", function (data) {
	  return {
	      user: response
	  }
	});
  },

With the code above, the render()-method does not wait for data to be succeed ( render()-method seems not the callback of data()-method).

The render()-method returns “undefined” for “data”-object. I can do a promise or call that ajax within the render()-method and return only when data is fetched.

  • However, is this the right thing to do?
  • If so, how can I set the data-property afterwards within the render()-method.
  • Do I need to set this?

Should I use async(routeTo, routeFrom, resolve, reject) {…} for such cases?

docs:{
  Property:'render',
  Type:'function',
  Description:'Render function to render component. Must return full html string or HTMLElement'
}

//e.g

{
  path:'/plain-html/',
  component:{
    render:function(){
      return '<div class="page">\
                <div class="navbar">\
                  <div class="navbar-inner">\
                    <div class="title">'+this.title+'</div>\
                  </div>\
                </div>\
                <div class="page-content"></div>\
              </div>';
    },
    data: function () {
      return {
        title:'Component Page',
      }
    }
  }
},
{
  path:'/compiled-html/',
  component:{
    render:function(){
      var html='<div class="page">\
                  <div class="navbar">\
                    <div class="navbar-inner">\
                      <div class="title">{{title}}</div>\
                    </div>\
                  </div>\
                  <div class="page-content">\
                    <div class="list simple-list">\
                      <ul>\
                        {{#each names}}\
                          <li>{{this}}</li>\
                        {{/each}}\
                      </ul>\
                    </div>\
                  </div>\
                </div>';
      return Template7.compile(html)(this);
    },
    data: function () {
      return {
        title:'Component Page',
        names:['John','Vladimir','Timo']
      }
    }
  }
}

Thanks, but this was not the question. I know how to render components.

As you see in my example, the question is:

Where should I put my ajax when render() is not called by a promise of data()-method. Calling async within data()-method does not render()-method makes to wait for the data()-result. When doing asyn within render() (even with promise), component will be undefined.

data called in the beginning of component creation, before all lifecycle hooks and page events, so you can use data in them.

render() does not wait until data() has fetched the result from async request, hence it renders without appropriate data. Doing async within render, returns undefined for the component. No promise-chain…

vladimir already answered (async)
i thought you didn’t get the ‘render’ thing
my mistake

no problem. thanks for helping;) however, “async” is the only way, I think, because there is no promise/callback-connection between data() and render()…

yes, async works!

How can I put the data
coming from the async request
within the data()-object of the routeTo-Component?

Should I use context-property? But the “data” is not a template-data.

app.request.json('http://some-endpoint/', function (data) {
        resolve(
         
          {
            component: comp
          },
          // Custom template context (wrong place to put my data-response)
          {
            context: {
              users: data,
            },
          }
        );

I can put it into app.data. so no problem.