Skip to content

Instantly share code, notes, and snippets.

@NullVoxPopuli
Last active March 15, 2021 02:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NullVoxPopuli/567b7acf47448cee1f63fcb36e82cd66 to your computer and use it in GitHub Desktop.
Save NullVoxPopuli/567b7acf47448cee1f63fcb36e82cd66 to your computer and use it in GitHub Desktop.
RFC 712: { scope: controller }
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
export default class ApplicationController extends Controller {
@service router;
get qps() {
return this.router.currentRoute.queryParams;
}
}
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
export default class ArticlesController extends Controller {
queryParams = [{
_amount: {
scope: 'controller'
}
}];
@service router;
// Read-only Query Param
// Encourages Query Params to only be changed via transition
get amount() {
// Because controllers implicity set properies that match entries
// in the queryParams array, we cannot have naming conflicts
// between getters and the Query Params
// (Until RFC 715: https://github.com/emberjs/rfcs/pull/715)
return this.router.currentRoute.queryParams._amount;
}
get filteredArticles() {
let { articles } = this.model;
return articles.slice(0, this.amount);
}
}
import { helper } from '@ember/component/helper';
export default helper(function stringify(params/*, hash*/) {
return JSON.stringify(params[0], null, 4);
});
import EmberRouter from '@ember/routing/router';
import config from './config/environment';
const Router = EmberRouter.extend({
location: 'none',
rootURL: config.rootURL
});
Router.map(function() {
this.route('articles', { path: '/articles/:byType' });
});
export default Router;
import Route from '@ember/routing/route';
export default class Articles extends Route {
// byType: ask, show, job
async model({ byType }) {
let stories = await storiesForType(byType);
return {
articles: stories,
};
}
}
// --------------------------------------------------------
async function storiesForType(type) {
let mostRecent = await latestStories(type);
// N+1 Query, yay!
let stories = await Promise.all(mostRecent.map(id => getItem(id)));
return stories;
}
async function getItem(id) {
return await get(`https://hacker-news.firebaseio.com/v0/item/${id}.json`);
}
async function get(url) {
let response = await fetch(url);
return await response.json();
}
async function latestStories(type) {
let latest = await get(`https://hacker-news.firebaseio.com/v0/${type}stories.json`);
let mostRecent = latest.slice(0, 30 /* some value bigger than we use for the demo query params */);
return mostRecent;
}
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
h1 {
margin-bottom: 0.5rem;
}
.flex {
display: flex;
}
.gap-4 {
gap: 1rem;
}
<h1>Example for <a target="_blank" href="https://github.com/emberjs/rfcs/pull/712">RFC 712</a></h1>
<em>Query Params as Derived Data</em>
<br>
<small><code>{ scope: 'controller' }</code> does not affect derived data patterns.</small>
<small>
Normally a controller's queryParam value is scoped to the model.
scope: controller makes the value persist across model values.
</small>
<pre>
QPs: {{stringify this.qps}}
URL: {{this.router.currentURL}}
</pre>
<br>
<nav class="flex gap-4">
{{!--
Query Params set on a controller are "sticky"
So to get rid of them, we must explicitly set to *undefined*
This will not scale for lots of Query Params
- See related RFC: https://github.com/emberjs/rfcs/pull/715
--}}
<LinkTo @route="articles" @model="ask">
AskHN
</LinkTo>
<LinkTo @route="articles" @model="show">
ShowHN
</LinkTo>
</nav>
<nav class="flex gap-4">
Per Page:
<LinkTo @query={{hash _amount=5}}>5</LinkTo>
<LinkTo @query={{hash _amount=10}}>10</LinkTo>
</nav>
<hr>
{{outlet}}
<br>
<br>
{{#each this.filteredArticles as |article|}}
<div>
{{log article}}
{{article.score}} | <a target="_blank" href={{article.url}}>{{article.title}}</a>
<br>
<em>by {{article.by}}</em>
<hr>
</div>
{{/each}}
{
"version": "0.17.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": false
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1"
},
"addons": {
"@glimmer/component": "1.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment