Skip to content

Instantly share code, notes, and snippets.

@jwlawrence
Last active April 30, 2017 23:54
Show Gist options
  • Save jwlawrence/0334972688d8ccf699b820d783f1b624 to your computer and use it in GitHub Desktop.
Save jwlawrence/0334972688d8ccf699b820d783f1b624 to your computer and use it in GitHub Desktop.
ember-tri-state
import Ember from 'ember';
const { computed, Controller } = Ember;
export default Controller.extend({
showLastSuccessful: true,
actions: {
resetShowLastSuccessful() {
this.set('showLastSuccessful', true);
},
flushAndRefreshModel() {
this.set('showLastSuccessful', false);
return true;
},
},
});
import Ember from 'ember';
const { Route, run } = Ember;
export default Route.extend({
model() {
return {
lastUpdated: new Date(),
postRequest: this.getPost(),
commentsRequest: this.getComments(),
adsRequest: this.getAds(),
}
},
getPost() {
return new Promise((resolve, reject) => {
run.later(this, () => {
resolve({
id: 1,
title: "This is the Post Title",
body: "Quia et suscipit suscipit recusandae consequuntur expedita et cum reprehenderit molestiae ut ut quas totam nostrum rerum est autem sunt rem eveniet architecto"
});
}, 1500);
});
},
getComments() {
return new Promise((resolve, reject) => {
run.later(this, () => {
resolve([
{
id: 1,
name: "Elise",
email: "[email protected]",
body: "Laudantium enim quasi est quidem magnam voluptate!"
},
{
id: 2,
name: "Jayne",
email: "[email protected]",
body: "Est natus enim nihil est dolore."
}
]);
}, 3000);
});
},
getAds() {
return new Promise((resolve, reject) => {
run.later(this, () => {
reject({ message: 'There was an error fetching ads' });
}, 5000)
});
},
actions: {
flushAndRefreshModel() {
this.refresh();
},
refreshModel() {
this.refresh();
}
},
});
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
.controls {
padding: 0 2% 20px;
}
.content {
display: flex;
flex-flow: row wrap;
}
.card {
background: rgb(245,245,245);
border-radius: 20px;
flex: 1 1 46%;
margin: 0 2% 20px;
padding: 0 20px;
position: relative;
overflow: hidden;
}
.card--full {
flex: 1 1 100%;
}
.post,
.comments {
position: relative;
}
.loader {
background: lightskyblue;
border-radius: 10px;
color: white;
padding: 6px 12px;
position: absolute;
top: 10px;
right: 10px;
}
.spinner {
font-style: italic;
margin: 20px auto;
}
.spinner:before {
content: '';
box-sizing: border-box;
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
margin-top: -10px;
margin-left: -10px;
border-radius: 50%;
border-top: 2px solid #07d;
border-right: 2px solid transparent;
animation: spinner .6s linear infinite;
}
@keyframes spinner {
to {transform: rotate(360deg);}
}
<header class="controls">
<button {{action 'refreshModel'}}>Reload Data</button>
<button {{action 'flushAndRefreshModel'}}>Flush and Reload Data</button>
</header>
<main class="content">
{{#tri-state
promises=model.adsRequest
loadingComponent="x-loading"
errorComponent="x-error"
as |tri|
}}
<div class="card card--full">
<h4>Ads</h4>
{{tri.loading}}
{{tri.error}}
{{#tri.success as |data|}}
<p>Ad goes here</p>
{{/tri.success}}
</div>
{{/tri-state}}
{{#tri-state
promises=(hash
post=model.postRequest
comments=model.commentsRequest
)
showLastSuccessful=showLastSuccessful
loadingComponent='x-loading'
onFulfilledData=(action 'resetShowLastSuccessful')
as |tri|
}}
<div class="card">
<h4>Post (load post and comments together)</h4>
{{tri.loading}}
{{#tri.error as |error|}}
<h1>Error Component</h1>
<p>{{error.message}}</p>
{{/tri.error}}
{{#tri.success as |data|}}
{{#if tri.isLoading}}
<div class="loader">Updating...</div>
{{/if}}
{{#x-post post=data.post comments=data.comments as |post comments|}}
<p>Last updated: {{model.lastUpdated}}</p>
<h1>{{post.title}}</h1>
<p>{{post.body}}</p>
<h2>Comments</h2>
{{#each comments as |comment|}}
<p><em>{{comment.email}}</em> wrote:</p>
<p>{{comment.body}}</p>
<hr>
{{/each}}
{{/x-post}}
{{/tri.success}}
</div>
{{/tri-state}}
<div class="card">
<h4>Post (load post and comments separately)</h4>
<div class="post">
{{#tri-state
promises=model.postRequest
loadingComponent='x-loading'
errorComponent="x-error"
as |tri|
}}
{{#tri.loading}}
<div class="spinner">Loading Post...</div>
{{/tri.loading}}
{{tri.error}}
{{#tri.success as |post|}}
<p>Last updated: {{model.lastUpdated}}</p>
<h1>{{post.title}}</h1>
<p>{{post.body}}</p>
{{/tri.success}}
{{/tri-state}}
</div>
<div class="comments">
{{#tri-state
promises=model.commentsRequest
errorComponent="x-error"
as |tri|
}}
{{tri.error}}
{{#tri.loading}}
<div class="spinner">Loading Comments...</div>
{{/tri.loading}}
{{#tri.success as |comments|}}
<h2>Comments</h2>
{{#each comments as |comment|}}
<p><em>{{comment.email}}</em> wrote:</p>
<p>{{comment.body}}</p>
<hr>
{{/each}}
{{/tri.success}}
{{/tri-state}}
</div>
</div>
</main>
{{#if hasBlock}}
{{yield data}}
{{else}}
<p>{{data.message}}</p>
{{/if}}
{{#if hasBlock}}
{{yield}}
{{else}}
<div class="spinner"></div>
{{/if}}
{{#if hasBlock}}
{{yield post comments}}
{{else}}
<h1>Success component</h1>
{{/if}}
{
"version": "0.12.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.11.2",
"ember-data": "2.12.1",
"ember-template-compiler": "2.11.2",
"ember-testing": "2.11.2"
},
"addons": {
"ember-concurrency": "0.8.1",
"ember-tri-state": "1.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment