i'm trying to get data from my api, the code for getting datas :
getList() {
this.fileList = [];
this._globalService.getUserFiles(this.userId)
.then(files => {
files.forEach(retFile => {
this._globalService.getFileActions(retFile._id)
.then(retActions => {
this.fileList.push( {
file: retFile,
action: retActions
});
});
});
})
.finally(() => {
this.finish = true;
});
}
Call OnInit hook.
After, my view is trying to show same that :
<ng-container *ngIf="finish; else wait">
<ng-container *ngIf="fileList.length; else noItems">
<li *ngFor="let item of fileList">
...
</li>
<ng-container>
<ng-template #noItems>
<span class="noItems">Any file</span>
</ng-template>
<ng-container>
That works fine.
But my problem lasts a few seconds the #noItems template is to show when datas exists, like in this example :
You always push your result into this.FileList, you this.FileList never empty, therefore your noItem template never show up.
Related
My goal is to store a specific data in the localStorage when I click on a link
but log i get is either undefined or absolutely nothing.
<li v-for="(categorie, index) in categories" :key="index">
<a href="./currentCategory" #click.prevent="getCategory()">
<img class="categorie-img" :src="categorie.strCategoryThumb" >
<p>{{ categorie.strCategory }}</p>
</a>
</li>
data() {
return {
categories: []
}
},
methods: {
getAllCategories() {
axios
.get('https://www.themealdb.com/api/json/v1/1/categories.php')
.then((response) => {
console.log( response.data);
this.categories = response.data.categories;
}).catch(error => {
console.log(error);
alert("api can't be reached");
})
},
getCategory() {
localStorage.setItem('currentCategory', this.categorie.strCategory );
}
},
I am using this API https://www.themealdb.com/api/json/v1/1/categories.php
I guess this.categorie.strCategory is incorrect but i really cant figure it out
I also tried this.categories.strCategory
Try to pass category
#click.prevent="getCategory(categorie)
then save it
getCategory(cat) {
localStorage.setItem('currentCategory', cat );
}
Found the answer thanks to #Nikola Pavicevic
had to pass a category to the click event
#click.prevent="getCategory(categorie.strCategory)
and pass it to the function
getCategory(cat) {
localStorage.setItem('currentCategory', cat);
}
In my code, I am displaying a paragraph and I want the user to change that paragraph and save it. So that the paragraph is updated and new. The component on which the text is displayed is a side panel of the main page. The code works, the user can edit the data and when saved, you can see it's updated in the network. But when I reopen the page, the old text is back as if I haven't done anything to it even though it has changed. My code is below, I searched, but I can't figure out the problem and what should I do to fix it.
HTML:
<div class="h-100-p" fxLayout="column" fusePerfectScrollbar>
<div class="group mt-32">
<div fxLayoutAlign="start center">
<header class="purple-fg" style="font-size:18.72px"><strong>Sticker Info:</strong></header>
</div>
<p>
<span contenteditable [textContent]="_stickerData?.StickerData" (input)="onStickerDataChange($event.target.innerHTML)">
{{_stickerData?.StickerData}}
</span>
</p>
</div>
</div>
<button mat-button matRipple class="purple-500 fuse-white-fg mr-12" (click)="save()"> Update Sticker </button>
TS:
private _stickerData: IStickerData;
#Input()
set StickerData(prm: IStickerData) {
if (this._stickerData != prm) {
this._stickerData = prm;
}
}
get StickerData(): IStickerData {
return this._stickerData;
}
dataSource: MatTableDataSource<IStickerData>;
constructor(
private _productionService: ProductionService,
private cd: ChangeDetectorRef,
) {}
ngOnInit() {
}
onStickerDataChange(data) {
this._stickerData.StickerData = data;
}
save(){
this.confirmDialogRef = this._dialog.open(FuseConfirmDialogComponent, {
disableClose: false,
});
this.confirmDialogRef.componentInstance.confirmMessage =
"Sticker will be changed.";
this.confirmDialogRef.afterClosed().subscribe((result) => {
if (result) {
this._productionService
.saveStickerData(this._stickerData)
.subscribe((response: IStickerData) => {
this._stickerData = response;
this._messages.Show(
"Sticker is updated",
3
);
this.cd.markForCheck();
});
}
});
}
TS for service:
saveStickerData(data: IStickerData): Observable<IStickerData> {
return this._http.post("Production/SaveStickerData", data);
}
You need to fetch the data from where it's being saved.
Update your service file by adding a get function for the data. Something like...
production.service.ts
getStickerData(): Observable<IStickerData> {
return this.httpClient.get("Production/GetStickerData")
}
Then invoke the function in your app component:
app.component.ts
ngOnInit() {
this.productionService.getStickerData()
.subscribe(data => this._stickerData.StickerData = data)
}
That should populate the paragraph with saved and updated data from production...
Template html
<div class="item" v-for="n, index in teamRoster">
<span> {{ getFantasyScore(n.personId) }} </span>
</div>
Method
getFantasyScore(playerId) {
if(playerId) {
axios.get(config.NBLAPI + config.API.PLAYERFANTASYSCORE + playerId)
.then( (response) => {
if( response.status == 200 ) {
console.log(response.data.total)
return response.data.total;
}
});
}
}
I'm trying to display the returned data to DOM but it doesnt display anything. But when I try to console log the data is displays. How can I be able to display it. What am I missing?
Problem is, your getFantasyScore method doesn't return anything and even then, the data is asynchronous and not reactive.
I would create a component that loads the data on creation. Something like
Vue.component('fantasy-score', {
template: '<span>{{score}}</span>',
props: ['playerId'],
data () {
return { score: null }
},
created () {
axios.get(config.NBLAPI + config.API.PLAYERFANTASYSCORE + this.playerId)
.then(response => {
this.score = response.data.total
})
}
})
and then in your template
<div class="item" v-for="n, index in teamRoster">
<fantasy-score :player-id="n.personId"></fantasy-score>
</div>
You shouldn't use methods for AJAX results because they are async. You could retrieve the full teamRoster object and then add this to your div:
<div class="item" v-for="fantasyScore in teamRoster" v-if="teamRoster">
<span> {{ fantasyScore }} </span>
</div>
i have problem. When I click the button, it receives an entire database, but I want laod part database. How can I do this?
For example: After every click I would like to read 10 posts.
Thx for help.
Messages.vue:
<div class="chat__messages" ref="messages">
<chat-message v-for="message in messages" :key="message.id" :message="message"></chat-message>
<button class="btn btn-primary form-control loadmorebutton" #click="handleButton">Load more</button>
</div>
export default{
data(){
return {
messages: []
}
},
methods: {
removeMessage(id){...},
handleButton: function () {
axios.get('chat/messagesmore').then((response) => {
this.messages = response.data;
});
}
},
mounted(){
axios.get('chat/messages').then((response) => {
this.messages = response.data
});
Bus.$on('messages.added', (message) => {
this.messages.unshift(message);
//more code
}).$on('messages.removed', (message) => {
this.removeMessage(message.id);
});
}
}
Controller:
public function index()
{
$messages = Message::with('user')->latest()->limit(20)->get();
return response()->json($messages, 200);
}
public function loadmore()
{
$messages = Message::with('user')->latest()->get();
// $messages = Message::with('user')->latest()->paginate(10)->getCollection();
return response()->json($messages, 200);
}
paginate(10) Loads only 10 posts
You can do it like this:
<div class="chat__messages" ref="messages">
<chat-message v-for="message in messages" :key="message.id" :message="message"></chat-message>
<button class="btn btn-primary form-control loadmorebutton" #click="handleButton">Load more</button>
</div>
export default{
data(){
return {
messages: [],
moreMessages: [],
moreMsgFetched: false
}
},
methods: {
removeMessage(id){...},
handleButton: function () {
if(!this.moreMsgFetched){
axios.get('chat/messagesmore').then((response) => {
this.moreMessages = response.data;
this.messages = this.moreMessages.splice(0, 10);
this.moreMsgFetched = true;
});
}
var nextMsgs = this.moreMessages.splice(0, 10);
//if you want to replace the messages array every time with 10 more messages
this.messages = nextMsgs
//if you wnt to add 10 more messages to messages array
this.messages.push(nextMsgs);
}
},
mounted(){
axios.get('chat/messages').then((response) => {
this.messages = response.data
});
Bus.$on('messages.added', (message) => {
this.messages.unshift(message);
//more code
}).$on('messages.removed', (message) => {
this.removeMessage(message.id);
});
}
}
-initialize a data property morMsgFetched set to false to indicate if more messages are fetched or not
if morMsgFetched is false make the axios request and st the response to moreMessages, then remove 10 from moreMessages and set it to messages[]..
After that set morMsgFetched to true
on subsequest click remove 10 from moreMessages and push it to 'messages[]`
Use Laravels built in pagination.
public function index()
{
return Message::with('user')->latest()->paginate(20);
}
It returns you next_page url which you can use to get more results calculated automatically
This might be too late but i believe the best way to do it is using pagination, Initially onMounted you'll send a request to let's say /posts?page=1, the one is a variable let's say named 'pageNumber', each time the user clicks on the "Load More" button, you'll increment the pageNumber and resent the request, the link will page /posts?page=2 this time, at this point you can append the results you've got to the already existing one and decide if the Load More button should be shown based on the last_page attribute returned by laravel paginator...
I'm sure you already solved your problem or found another alternative, this might be usefull for future developers.
I'm working on a mini-project to brush up on my Angular but it seems I forgot more than I thought. I'm using 2 components weather-search and display-weather and they communicate through the HomeController. Now, what happens is this, when I enter a value (either city or zip) and submit the form, the console will log the return with the JSON data from the API, but it won't display in the UI unless the form is re-submitted then it will update with the search result, essentially, every second submit will update the UI. Why? :(
app.js
var angular = require('angular')
angular.module(`weather_app`, [])
.controller('HomeController', function(){
this.data = ''
})
require('./services/index')
require('./components/weather-search')
require('./components/display-weather')
weather-search.js
angular.module('weather_app')
.component('weatherSearch', {
templateUrl: './templates/weather.html',
bindings: {
weather: '&'
},
controller: WeatherSearchController
})
function WeatherSearchController(WeatherService, CountryService){
var ctrl = this
ctrl.title = "Weather App!"
ctrl.searchWeather = function(data) {
// ...
WeatherService.getCurrent(data.option, data.value)
.then( result => {
// ...
ctrl.weather({$event: {data: result}})
})
.catch( error => {
console.error(error)
})
}
}
display-weather.js
angular.module('weather_app')
.component('displayWeather', {
template:`
Display: {{ $ctrl.weather }}
`,
bindings: {
weather: '<'
}
})
weather.pug
div(class="weather")
h1.
{{ ::$ctrl.title }}
div(class="weather-search")
form
select(ng-init="weather.option = weather.option || 'zip'", ng-model="weather.option")
option(value="zip").
Zip Code
option(value="city").
City
input(class="weather-search-input", ng-model="weather.value")
select(ng-init="weather.type = weather.type || 'f'", ng-model="weather.type")
option(value="f").
Fahrenheit
option(value="c").
Celsius
option(value="k").
Kelvin
button(type="submit", ng-click="$ctrl.searchWeather(weather)").
Search
div(ng-if="$ctrl.error", class="error").
{{ $ctrl.error }}