Skip to content

Instantly share code, notes, and snippets.

@dha-corey
Last active March 7, 2020 20:23
Show Gist options
  • Save dha-corey/534bf9240a8b8ab1381918cbc9576a28 to your computer and use it in GitHub Desktop.
Save dha-corey/534bf9240a8b8ab1381918cbc9576a28 to your computer and use it in GitHub Desktop.
SDC2020 - Vue Workshop
license: mit
async function fetchData(cb) {
return fetch('oilers.json')
.then(async resp => resp.json())
}
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="fetch_data.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<div id="app">
<h1>Goals in blue, assists in red</h1>
<h3>{{totalGoals}} total goals, {{totalPoints}} total points</h3>
<bar-chart title="forwards" v-bind:players="forwards"></bar-chart>
<bar-chart title="defensemen" v-bind:players="defensemen"></bar-chart>
<goal-scorer
v-bind:players="players"
v-on:score-goal="scoreGoal"
v-on:score-assist="scoreAssist">
</goal-scorer>
</div>
<script>
Vue.component('bar-chart', {
template: `
<svg width="350" height="600">
<text x="5" y="20" >{{title}}</text>
<rect v-for="(player, i) in players"
v-bind:width="player.G * 2"
v-bind:height="18"
x="5"
v-bind:y="i * 20 + 25"
style="fill:blue"
></rect>
<rect v-for="(player, i) in players"
v-bind:width="player.A * 2"
v-bind:height="18"
v-bind:x="player.G * 2 + 5"
v-bind:y="i * 20 + 25"
style="fill:red"
></rect>
<text v-for="(player, i) in players"
v-bind:x="(player.G + player.A) * 2 + 10"
v-bind:y="i * 20 + 40">
{{player.Player}}
</text>
</svg>
`,
props: {
title: String,
players: Array
}
});
/**
* v-bind does one-way binding:
* v-bind:value="i" means that when i changes, value is updated
*
* v-model does two-way binding:
* v-model="currentPlayerIndex" means that:
* when currentPlayerIndex changes, the select's value is updated
* when the select's value changes, currentPlayerIndex is updated
*/
Vue.component('goal-scorer', {
template: `
<div>
<select v-model="currentPlayerIndex">
<option
v-for="(player, i) in players"
v-bind:value="i"
>{{player.Player}}</option>
</select>
<button v-on:click="scoreGoal">Goal</button>
<button v-on:click="scoreAssist">Assist</button>
</div>
`,
data() {
return {
currentPlayerIndex: null
}
},
props: {
players: Array
},
methods: {
scoreGoal() {
// Emitting an event in this component lets us watch it
// in the parent:
// i.e. v-on:score-goal="doSomething"
this.$emit('score-goal', this.currentPlayerIndex);
},
scoreAssist() {
this.$emit('score-assist', this.currentPlayerIndex);
}
}
})
var vueApp = new Vue({
el: '#app',
data() {
return {
players: []
}
},
computed: {
defensemen() {
return this.players.filter(p => p.Pos === 'D')
},
forwards() {
return this.players.filter(p => p.Pos !== 'D')
},
totalGoals() {
var g = 0;
for(var i = 0; i < this.players.length; i++) {
g += this.players[i].G;
}
return g;
},
totalPoints() {
var p = 0;
for(var i = 0; i < this.players.length; i++) {
p += this.players[i].G + this.players[i].A;
}
return p;
},
},
methods: {
scoreGoal(index) {
this.players[index].G++;
},
scoreAssist(index) {
this.players[index].A++;
}
}
});
fetchData().then(function(data) {
vueApp.players = data;
});
</script>
</body>
[{"Player":"Leon Draisaitl","Pos":"C","GP":68,"G":43,"A":67,"P":110},{"Player":"Connor McDavid","Pos":"C","GP":62,"G":32,"A":63,"P":95},{"Player":"Ryan Nugent-Hopkins","Pos":"C","GP":62,"G":21,"A":38,"P":59},{"Player":"Oscar Klefbom","Pos":"D","GP":59,"G":5,"A":28,"P":33},{"Player":"Zack Kassian","Pos":"R","GP":56,"G":15,"A":17,"P":32},{"Player":"Darnell Nurse","Pos":"D","GP":68,"G":5,"A":27,"P":32},{"Player":"James Neal","Pos":"L","GP":52,"G":19,"A":10,"P":29},{"Player":"Kailer Yamamoto","Pos":"R","GP":24,"G":11,"A":13,"P":24},{"Player":"Alex Chiasson","Pos":"R","GP":62,"G":9,"A":12,"P":21},{"Player":"Ethan Bear","Pos":"D","GP":68,"G":5,"A":16,"P":21},{"Player":"Josh Archibald","Pos":"R","GP":59,"G":12,"A":8,"P":20},{"Player":"Riley Sheahan","Pos":"C","GP":63,"G":7,"A":7,"P":14},{"Player":"Sam Gagner","Pos":"C","GP":36,"G":5,"A":7,"P":12},{"Player":"Gaetan Haas","Pos":"C","GP":57,"G":5,"A":5,"P":10},{"Player":"Jujhar Khaira","Pos":"L","GP":61,"G":6,"A":3,"P":9},{"Player":"Joakim Nygard","Pos":"L","GP":33,"G":3,"A":6,"P":9},{"Player":"Caleb Jones","Pos":"D","GP":41,"G":3,"A":5,"P":8},{"Player":"Matt Benning","Pos":"D","GP":41,"G":1,"A":7,"P":8},{"Player":"Kris Russell","Pos":"D","GP":53,"G":0,"A":8,"P":8},{"Player":"Adam Larsson","Pos":"D","GP":46,"G":1,"A":5,"P":6},{"Player":"Patrick Russell","Pos":"R","GP":45,"G":0,"A":5,"P":5},{"Player":"Markus Granlund","Pos":"C","GP":34,"G":3,"A":1,"P":4},{"Player":"Tyler Ennis","Pos":"C","GP":6,"G":1,"A":2,"P":3},{"Player":"Andreas Athanasiou","Pos":"L","GP":6,"G":1,"A":1,"P":2},{"Player":"Tomas Jurco","Pos":"R","GP":12,"G":0,"A":2,"P":2},{"Player":"Joel Persson","Pos":"D","GP":13,"G":0,"A":2,"P":2},{"Player":"Colby Cave","Pos":"C","GP":11,"G":1,"A":0,"P":1},{"Player":"Brandon Manning","Pos":"D","GP":9,"G":1,"A":0,"P":1},{"Player":"Tyler Benson","Pos":"L","GP":7,"G":0,"A":1,"P":1},{"Player":"William Lagesson","Pos":"D","GP":8,"G":0,"A":0,"P":0},{"Player":"Mike Green","Pos":"D","GP":2,"G":0,"A":0,"P":0}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment