Vue JS
Get locations
A static example of the Final Space API using Vue JS and/or Axios.
This example uses /location
endpoint of the Final Space API.
Below each example is image of the output of the code and the link to the example on StackBlitz.
More details to using limit and other query's an be found in Location endpoint.
- Vue + Fetch API
- Vue + Axios
<template>
<div class="root">
<p v-if="loading">Loading...</p>
<div class="location" v-for="location in locations" :key="location.id">
<div class="location-image">
<img :src="location.img_url" :alt="location.name" />
</div>
<div class="location-desc">
<div class="location-title">{{ location.name }}</div>
<div class="location-type">{{ location.type }}</div>
</div>
<div class="location-inhabitants">
<span v-if="location.inhabitants.length == 0" class="none"
>No inhabitants</span>
<span
v-else
v-for="(inhabitant, index) in location.inhabitants"
:key="inhabitant"
>
<span v-if="index == location.inhabitants.length - 1">{{
inhabitant
}}</span>
<span v-else>{{ inhabitant }} <span class="spd">|</span></span>
</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Location",
data() {
return {
locations: [],
loading: false,
};
},
created() {
this.getLocations();
},
methods: {
getLocations() {
this.loading = true;
fetch("https://finalspaceapi.com/api/v0/location/?limit=3")
.then((res) => res.json())
.then((data) => (this.locations = data));
this.loading = false;
},
},
};
</script>
<style scoped>
.root {
margin: 0 auto;
padding: 0 10px;
font-family: Verdana;
font-weight: 300;
display: flex;
justify-content: space-around;
flex-direction: column;
align-items: center;
color: purple;
}
.location {
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.3);
padding: 12px;
margin-bottom: 10px;
text-align: center;
width: 18rem;
background-color: #fafafa;
margin-bottom: 15px;
border-radius: 7px;
}
.location-desc {
display: flex;
justify-content: space-between;
}
.location-image img {
width: 100%;
height: calc(16rem - 12px);
border-radius: 7px;
margin-bottom: 10px;
}
.location-title {
font-size: "1.1rem";
font-weight: 400;
}
.location-type {
color: rgb(107, 107, 107);
font-size: 0.9rem;
}
.location-inhabitants {
color: rgb(107, 107, 107);
text-align: left;
font-size: 0.9rem;
margin: 0.7rem 0;
}
.location-inhabitants span {
margin: 0 0.1rem;
}
.spd {
font-size: 1.1rem;
font-weight: 200;
color: rgb(223, 223, 223);
}
</style>
<template>
<div class="root">
<p v-if="loading">Loading...</p>
<p v-if="!loading && error">
{{error}}
<button @click="getLocations">Reload</button>
</p>
<div class="location" v-for="location in locations" :key="location.id">
<div class="location-image">
<img :src="location.img_url" :alt="location.name" />
</div>
<div class="location-desc">
<div class="location-title">{{ location.name }}</div>
<div class="location-type">{{ location.type }}</div>
</div>
<div class="location-inhabitants">
<span v-if="location.inhabitants.length == 0" class="none"
>No inhabitants</span
>
<span
v-else
v-for="(inhabitant, index) in location.inhabitants"
:key="inhabitant"
>
<span v-if="index == location.inhabitants.length - 1">{{
inhabitant
}}</span>
<span v-else>{{ inhabitant }} <span class="spd">|</span></span>
</span>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "LocationAx",
data() {
return {
locations: [],
loading: false,
error: null,
};
},
created() {
this.getLocations();
},
methods: {
async getLocations() {
this.loading = true;
try {
let res = await axios.get("https://finalspaceapi.com/api/v0/location/?limit=3");
this.locations = res.data;
this.error = null;
} catch(err){
this.error = "Unable to fetch locations"
}
this.loading = false;
},
},
};
</script>
<style scoped>
.root {
margin: 0 auto;
padding: 0 10px;
font-family: Verdana;
font-weight: 300;
display: flex;
justify-content: space-around;
flex-direction: column;
align-items: center;
color: purple;
}
.location {
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.3);
padding: 12px;
margin-bottom: 10px;
text-align: center;
width: 18rem;
background-color: #fafafa;
margin-bottom: 15px;
border-radius: 7px;
}
.location-desc {
display: flex;
justify-content: space-between;
}
.location-image img {
width: 100%;
height: calc(16rem - 12px);
border-radius: 7px;
margin-bottom: 10px;
}
.location-title {
font-size: "1.1rem";
font-weight: 400;
}
.location-type {
color: rgb(107, 107, 107);
font-size: 0.9rem;
}
.location-inhabitants {
color: rgb(107, 107, 107);
text-align: left;
font-size: 0.9rem;
margin: 0.7rem 0;
}
.location-inhabitants span {
margin: 0 0.1rem;
}
.spd {
font-size: 1.1rem;
font-weight: 200;
color: rgb(223, 223, 223);
}
</style>
Result
You can play with this example on StackBlitz.
Get Locations with Characters
The example below shows location with a limit of 3, and a preview of all notable characters in the location
<template>
<div class="root">
<p v-if="loading">Loading...</p>
<p v-if="!loading && error">
{{ error }}
<button @click="getLocations">Reload</button>
</p>
<div class="location" v-for="location in locations" :key="location.id">
<div class="location-image">
<img :src="location.img_url" :alt="location.name" />
</div>
<div class="location-desc">
<div class="location-title">{{ location.name }}</div>
<div class="location-type">{{ location.type }}</div>
</div>
<div class="location-inhabitants">
<span v-if="location.inhabitants.length == 0" class="none"
>No inhabitants</span
>
<span
v-else
v-for="(inhabitant, index) in location.inhabitants"
:key="inhabitant"
>
<span v-if="index == location.inhabitants.length - 1">{{
inhabitant
}}</span>
<span v-else>{{ inhabitant }} <span class="spd">|</span></span>
</span>
</div>
<div class="notable_residents">
<span
v-for="notable_resident in location.notable_residents_data"
:key="notable_resident.id"
>
<span
><img
:title="notable_resident.name"
class="notable_resident_img"
:src="notable_resident.img_url"
:alt="notable_resident.name"
/></span>
</span>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "LocationCharacter",
data() {
return {
locations: [],
notable_residents: [],
loading: false,
error: null,
};
},
created() {
this.getLocations();
},
methods: {
async getLocations() {
this.loading = true;
try {
let res = await axios.get(
"https://finalspaceapi.com/api/v0/location/?limit=3"
);
this.locations = res.data;
this.getNotableResident();
this.error = null;
} catch (err) {
this.error = "Unable to fetch locations";
console.log(err);
}
this.loading = false;
},
getNotableResident(locations) {
// Loop through locations to create notable_residents_img array
this.locations.forEach((location, index) => {
this.locations[index].notable_residents_data = [];
});
let newLocations = [...this.locations];
newLocations.forEach(async (location, index) => {
this.locations = newLocations;
if (location.notable_residents.length !== 0) {
await location.notable_residents.forEach(async (resident) => {
axios.get(resident).then((res) => {
newLocations[index].notable_residents_data.push(res.data);
this.locations = newLocations;
// For some reasons Vue doesn't re-render, so this is a force re-render
this.$forceUpdate();
});
});
}
});
},
},
};
</script>
<style scoped>
.root {
margin: 0 auto;
padding: 0 10px;
font-family: Verdana;
font-weight: 300;
display: flex;
justify-content: space-around;
flex-direction: column;
align-items: center;
color: purple;
}
.location {
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.3);
padding: 12px;
margin-bottom: 10px;
text-align: center;
width: 18rem;
background-color: #fafafa;
margin-bottom: 15px;
border-radius: 7px;
flex-wrap: wrap;
}
.location-desc {
display: flex;
justify-content: space-between;
}
.location-image img {
width: 100%;
height: calc(16rem - 12px);
border-radius: 7px;
margin-bottom: 10px;
}
.location-title {
font-size: "1.1rem";
font-weight: 400;
}
.location-type {
color: rgb(107, 107, 107);
font-size: 0.9rem;
}
.location-inhabitants {
color: rgb(107, 107, 107);
text-align: left;
font-size: 0.9rem;
margin: 0.7rem 0;
}
.location-inhabitants span {
margin: 0 0.1rem;
}
.notable_residents {
text-align: left;
margin: 0.7rem 0;
}
.notable_resident_img {
width: 35px;
height: 35px;
border-radius: 25px;
margin: 0.5rem 0.05rem;
}
</style>
Result
You can play with this example on StackBlitz.