Skip to content
This repository has been archived by the owner on Apr 21, 2021. It is now read-only.

Ajax Load Pattern Component #167

Open
joesnellpdx opened this issue May 26, 2017 · 8 comments
Open

Ajax Load Pattern Component #167

joesnellpdx opened this issue May 26, 2017 · 8 comments
Assignees
Labels

Comments

@joesnellpdx
Copy link
Contributor

It would be nice to have an example of ajax loading content (i.e. load more posts) as it seems to be different on every project. I'm not sure if the component library or best practices is the right place, but I'd sure love to know the 'ideal' patterns in a basic sense.

Of course, it is situational, but what is the best pattern for the following, or is there a general preference (situational excluded)?:

  • AJAX call to the REST API
  • admin-ajax.php
  • custom rewrite endpoint
@timwright12
Copy link
Contributor

@joesnellpdx what do you think something like this would look like in a component?

@joesnellpdx
Copy link
Contributor Author

@timwright12
Could go down a few directions here, but lately - I'm thinking a self contained vue component that can be passed params. A lot has changed since I wrote that question.

Maybe something I can put my mind to during my PRI. What do you think?

@timwright12
Copy link
Contributor

timwright12 commented Oct 4, 2018

@joesnellpdx how about something that's platform independent, like a web component?

@joesnellpdx
Copy link
Contributor Author

@timwright12

That is definitely a possibility. Good idea.

@dkoo
Copy link
Contributor

dkoo commented May 23, 2019

I've done a lot of these in various projects and in my experience, the smoothest implementations have involved:

  • Using the REST API: you get a ton out of the box with endpoints like /posts just by passing different query params, and devs can always create custom endpoints if they need something more customized. Most of the time, front-enders will be able to implement the feature this way without any help from back-enders.
  • Vanilla JS using no frameworks: I think this makes the most sense for a generalized component.
  • Using the good old XMLHttpRequest API for fetching data: It works in all browsers and has no dependencies (not even jQuery). fetch would be even better but it requires a polyfill for IE support. AJAX assumes that jQuery will always be available, which is becoming the case less and less.
  • Building the HTML to be appended in JS, instead of in PHP: Gives better control over each piece of content to be appended to the DOM. Building the HTML as a string in PHP—even if it's properly sanitized on the server side—will always trigger security warnings in platforms like VIP because there's no real way to get that content into the DOM without something like innerHTML or $.append. Building it in JS allows you to explicitly ensure that any user-inputted content is sanitized before being rendered. Also gets around not being able to demo with WP back-end functionality in the component library site.

All that being said, I took a stab at putting something together as an exercise in thinking about how this could be componentized. You can see it here (most of the functionality exists in this JS file): https://github.com/dkoo/component-load-more/blob/master/src/load-more.js

Building out this sketch brought up some important questions that I think warrant further discussion here.

  • How should we define how the post content is structured? I've used the blogroll component markup, but there's potential for these two components for getting out of sync with each other and we'd always have to remember to make matching updates in both components.
  • Speaking of the dynamic markup, how do we provide a user-friendly way to customize it? I imagine that most of the time, engineers will want to alter the markup for their own projects.
    • Currently, for proof of concept purposes, I'm building out the HTML using template strings. This seems to be the "cleanest" way to see and edit the HTML within the JS, compared with building out each element with document.createElement/element.setAttribute/element.textContent. However, using template strings means we would need to add an explicit sanitization step, and I'm not sure prescribing something like DOMPurify would be within the scope of this component library. Thoughts?
    • I also toyed with the idea of creating an invisible post element on the page with placeholder content, which the JS could clone and then replace the placeholder content for each post object. This could be a non-framework-dependent way to include a post "template" that can be easily customized, and wouldn't need a sanitization step since we wouldn't be dealing with executable strings. But it adds extra markup to the DOM and would require updates to both JS and HTML to customize the template.
  • How do we demo the functionality effectively? I'm currently using a public WP API demo built by Human Made which is currently mentioned in the WP Developer Handbook, but I'd imagine we'd like to demo something with 10up branding instead.
  • Do we need to mention things like CORS and offer options and guidance for cross-origin-related issues?
  • What other types of options and customizations should we support in a component like this?

Other limitations of my proof of concept worth mentioning:

  • It currently allows for only one area of "load more" functionality on the page. We could probably adapt it to handle multiple instances, if we clone the queryArgs object for each instance, as currently I'm mutating properties to handle things like paging and offset each time a request is sent.
  • No styles included, so it's pretty ugly.
  • Does not currently have an option for infinite scroll, but this would be relatively easy to implement with a scroll event handler.
  • Currently, wraps each batch of new posts in a div before appending to the DOM. I thought this could be useful in case people want to style each "page" of posts, but I'm not sure this is necessary/desired?

Anyway, I want to keep this discussion alive because it's something we build fairly often and I agree that the team could benefit from having a generalized approach to follow. I'm not sure what I've started should be that approach, but I think it's a good starting place to hash out some of these questions.

@timwright12
Copy link
Contributor

I think getting a component is a great idea and I like this as a starting point, but explicitly defining the template output like <h2 itemprop="headline"> is concerning if an h2 isn't the right answer for the page structure.

For it to be a true component in the library (and publish to NPM) it seems like we'd almost need to abstract everything out of the the file and into options and at some point it starts to become something else, right? Like a UI pattern or something that should be broken out into much smaller atomic elements and the result of collecting these elements together can be this loading pattern. Once it's broken down like that you can pass a lot of those decisions like CORS and sanitization onto the application rather than the component.

I could see us breaking the site out into components and patterns to get something like this sharable, because it definitely valuable.

@dkoo
Copy link
Contributor

dkoo commented May 31, 2019

@timwright12 How would you recommend moving the markup to options? Should we have an option that lets you pass a template string of sorts, with the default matching our blogroll component?

Or are you suggesting that we think of creating a new category of "patterns" in the component library, where they're not NPM packages that you can drop into your application, but more like recipes you can follow?

@timwright12
Copy link
Contributor

@dkoo I'm thinking of a new category of patterns that could be a collection of npm packages. For example, this pattern could be an example of using npm packages XY and Z to accomplish a "load more posts" functionality

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants