VueJS Widget which loads news from an API of "hr-filter.de".
- Display 5 Items per "site"
- get 5 new news onClick
- Layout with Bootstrap
A Pen by mschwrdtnr on CodePen.
<div class="container-fluid"> | |
<div id="app" class="align-self-center"> | |
<section v-if="errored"> | |
<p>Zugriff auf API ist derzeit nicht möglich. Bitte versuchen Sie es zu einem späteren Zeitpunkt.</p> | |
</section> | |
<section v-else> | |
<div v-if="loading">Loading...</div> | |
<news-tile v-for="news in filteredNews" | |
:news="news"> | |
</news-tile> | |
<div class="d-flex justify-content-center"> | |
<button class="btn btn-info btn-lg" | |
:disabled="isDisabled" | |
@click="loadMore">Mehr anzeigen | |
</button> | |
</div> | |
</section> | |
</div> | |
</div> |
Vue.component('news-tile', { | |
props: ['news'], | |
methods: { | |
convertDate(string) { | |
//toLocalString möglich | |
let options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; | |
let date = new Date(string).toLocaleDateString('de-DE', options); //Datum wird wieder in String umgewandelt, damit slice() verwendet werden kann | |
//Frage: Zeitformat ist irgendwie komisch. Bei euch in der api steht eine andere Zeit als in euren News. Habe es jetzt auch so gemacht und deswegen nochmal Time extra definiert. | |
let time = new Date(string).toString().slice(16,21); | |
return date + ", " + time + " Uhr"; | |
} | |
}, | |
template: | |
` | |
<div class="news_tile"> | |
<div class="row"> <!-- Header row --> | |
<div class="head_box col-sm-8"> | |
<div class="title"> | |
<a target="_blank" :href="news.original_url"> | |
<h3>{{ news.title }}</h3> | |
</a> | |
</div> | |
<div class="author"> | |
{{convertDate(news.published_at)}} | |
</div> | |
</div> | |
<div class="picture_box col-sm-4 align-self-center"> | |
<img :src="news.image.full_url" alt="Artikelbild"> | |
</div> | |
</div> | |
<div class="row"><!-- mid row --> | |
<div class="teaser-box col-sm-12"> | |
{{news.teaser}} | |
</div> | |
</div> | |
<div class="d-flex"><!-- bottom row --> | |
<div class="button-box ml-auto p-2"> | |
<a target="_blank" :href="news.original_url" class="btn btn-info">Mehr lesen</a> | |
</div> | |
</div> | |
</div> | |
` | |
}) | |
const app = new Vue({ | |
el: '#app', | |
data: { | |
all_news: [], | |
loading: true, | |
errored: false, | |
numOfItems: 5, //change this to load different number of items per load | |
sumItems: 5, //Start-Items | |
clicks: 0, //number of button-clicks | |
isDisabled: false | |
}, | |
computed: { | |
filteredNews () { | |
return this.all_news.slice(0, this.sumItems) | |
} | |
}, | |
methods: { | |
loadMore () { //es werden immer numOfItems neue Elemente des Arrays angezeigt | |
this.clicks++; | |
this.sumItems = this.clicks * this.numOfItems + this.numOfItems; | |
if(this.sumItems >= this.all_news.length){ //Falls News % 5 != 0 | |
this.sumItems = this.all_news.length | |
this.isDisabled = true; | |
} | |
} | |
}, | |
mounted () { | |
axios | |
.get('https://cors-anywhere.herokuapp.com/https://www.hrfilter.de/api/v1/news_items.json?order=month_best') | |
.then(response => { | |
this.all_news = response.data.news_items}) | |
.catch(error => { | |
console.log(error) | |
this.errored = true | |
}) | |
.finally(() => this.loading = false) | |
} | |
}) | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script> |
@import url('https://fonts.googleapis.com/css?family=Didact+Gothic'); | |
$color_blue: rgb(32,108,128); | |
$color_grey: #c2c2c2; | |
*{transition: all 0.4s;} | |
html, body{ | |
font-family: 'Didact Gothic', sans-serif; | |
margin: 1%; | |
scroll-behavior: smooth; | |
} | |
.news_tile{ | |
position: relative; | |
background: white; | |
left: 50%; | |
transform: translate(-50%,0); | |
width: 700px; | |
height: auto; | |
border: 1px solid $color_grey; | |
margin: 1%; | |
padding: 1%; | |
&:hover{ | |
//transform: scale(1.01); | |
border: 2px solid $color_blue; | |
} | |
} | |
.head_box{ | |
a{ | |
text-decoration: none; | |
} | |
h3{ | |
color: $color_blue; | |
} | |
.author{ | |
font-size: 16px; | |
color: $color_grey; | |
} | |
} | |
.picture_box{ | |
img{ | |
width: 100%; | |
} | |
} | |
.btn-info{ | |
background-color: $color_blue; | |
border: 0; | |
} | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" /> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css" rel="stylesheet" /> |
VueJS Widget which loads news from an API of "hr-filter.de".
A Pen by mschwrdtnr on CodePen.