nativescript-ngx-slides
nativescript-ngx-slides copied to clipboard
dynamic slides not working
hello, i am trying to use this plugin inside *ngFor
<slides pageIndicators="false" loop="false"> <slide *ngFor="let item of items; let i = index"> <GridLayout><Label [text]="i"></Label> </slide> </slides>
the plugin crashes and i am unable to slide between the slides
That's because the slides are created before the ngFor populates the dom. The slides aren't recreated after that though. I did somewhat hacky fix for that: slides are created first, then further recreation of slides is being done after 'changes' observable fires on ContentChildren. It's not ideal - changes to iterable ngFor is using will be reflected in the slides, but the slides may not be in correct order before first sliding action, resulting in slides jumping or not showing properly during the first slide after change. The other thing, because AFAIK "changes" observable isn't replaying content already emitted, slides have to be created once before subscribing to ContentChildren. If you want to try there's a "ngfor" branch on my fork, however keep in mind its not ideal solution.
@sarpt so what is the ideal solution?
i have the same problem, i get some info with a service from a DB to create dynamic slides but this happend. all the slides are on top of another.

this is part of my code
<slides id="slides" (changed)="slideChanged()" #slides > <slide class="slide" *ngFor="let number of items; let i = index;"> <ScrollView > <StackLayout *ngFor="let comp of items[i]">
@ChAraya I think the code called in the ngAfterViewInit (https://github.com/TheOriginalJosh/nativescript-ngx-slides/blob/master/slides/app/slides/slides.component.ts#L96) needs to be abstracted out into a public function you can then call after your dynamic data has loaded. This might be all you need to fix it. It's not a use cased i've had myself(yet) but I understand the need.
yea, a saw you solution to make a manualInit and i called but nothing happend
i need do something else ?

Hmm, I'm not sure really. could you open a Pull Request with your ManualInit in it? it would probably be a nice addition once the kinks are worked out.
ok, i will do it later, a question.
its there a way that i can know when the slides gonna be slide to other page ? before the change event occured?
'cause with that i can implement a parcial solution to my problem and make the slides "dynamic" but really not dynamic just know when no to slide to the next slide
I'm not sure I follow.
There are changed and finished events you can watch for https://github.com/TheOriginalJosh/nativescript-ngx-slides/blob/master/slides/app/slides/slides.component.ts#L62
+1 - is there a solution available in the meanwhile? I'm having the same problem. I have a first slide which comes from the view directly and further slides which comes dynamically from a json file which is loaded in the .ts
See code here: https://pastebin.com/G9EQXKMP

Looking forward for any help with this.
Thanks!
I fixed this by placing a ngIf into the slides tag that is checking weather the array is empty and only shows after data is laded into the array. Obviousely there is ap problem with changing the content of the array that is used in the ngfor. If there are changes maybe it also would help to make the array empty first and then set the refreshed data. then angular would rereder the slides-element (hopefully).
I have forked the project and changed the file slides.component.ts to init the slides only when there some (using ngAfterViewChecked). This way I can load the data asynchronously and use *ngFor to create the slide elements.
It is more a hack than a solution (and I don't have time to test it properly) but it works in my situation quite well -- maybe, you have a similar one. Here is the git repository: https://github.com/heese/nativescript-ngx-slides
@TheOriginalJosh Can this be an approach to solve the dynamic loading of slides? I create a pull request if you want to.
@heese that sounds great! good work man, thank you!
I like your plugin and I am happy to contribute.
Since I needed it I have also introduced a new attribute autoInit in my code (by default true) which allows me -- if set to false -- to manually trigger the initialisation.
That sounds perfect. Thank you @heese
Turned my hack into a solution (still no time to test it properly). You can subscribe to changes of QueryList and, thus, re-init the slides whenever they change. It is as simple as
this.slides.changes.subscribe(() => {
this._init();
});
Note: The dynamic data has to be loaded in ngAfterViewInit or later.
@heese Sorry to bother you, but could you provide an example of how are you using your fork?
I just need something to get me going, I could use your version, but the slides got badly initialized (not the right size).
Hi @gabitoesmiapodo
please find below an example which is derived from the code I am working on at the moment. In my case I needed the slides to have a certain width (depending on the display) and height (fixed). I have removed all unimportant bits and pieces and hope I haven't deleted anything essential -- meaning I have not tested the code below. Let me know if you need also the unmentioned import statements.
Furthermore, I copied the slides module into my project because Josh will hopefully update his code at some point (making my fork superfluous) and make it available on npm.
The method listLatestRedemptions does the async call to an endpoint for retrieving the data, e.g., something like return this.http.(url, options).
I found it helpful having the slides change automatically because you can then easily see if the slides are initialised properly and not rendered one over the other.
I hope it helps.
component.html:
<slides #slideShow [loop]="true" [pageHeight]="240" [pageWidth]="slideWidth">
<slide *ngFor="let item of redemptions">
<Label [text]="item.name + ' from ' + item.address"></Label>
</slide>
</slides>
component.ts:
import * as platform from "platform";
export class RedemptionComponent implements OnInit, AfterViewInit {
isLoading: boolean;
redemptions: LatestRedemption[] = [];
slideWidth: number;
@ViewChild('slideShow') slideView: SlidesComponent;
slideViewTimerId: number;
ngOnInit() {
super.ngOnInit();
// display width - 2 * padding 'inner-container'
this.slideWidth = Math.ceil(platform.screen.mainScreen.widthDIPs - 12);
}
ngAfterViewInit() {
this.loadLatestRedemptions();
}
loadLatestRedemptions() {
if (this.isLoading) {
return;
}
this.isLoading = true;
this.transactionService.listLatestRedemptions().subscribe(data => {
this.redemptions = data;
this.isLoading = false;
this.startAutoNextSlide();
}
);
}
startAutoNextSlide() {
if (!isNullOrUndefined(this.slideView)) {
this.slideViewTimerId = timer.setInterval(() => {
this.slideView.nextSlide(1000);
},
4000);
}
}
}
Thank you!
@heese please open a PR and I will merge it in. Thank you.
I have same issues, please see below code
slides.html
<slides pageIndicators="true" id="slides" #slides>
<slide class="slide-1" *ngFor="let player of players">
<Label [text]="player.name"></Label>
</slide>
</slides>
slides.component.ts
export class SlidesComponent implements OnInit {
players : Array<Player> = [];
@ViewChild("slides") slides: ElementRef;
ngOnInit() {
this.handlePlayer();
}
handlePlayer() {
//Call api and get data
this.players = data;
}
}
when i execute tns run android i got below response(overlap all player name)

how can i resolve it?
At a quick glance you are setting this.players too early. Try setting it in ngAfterViewInit. It might be that you need to use the code of the fork I created. (Haven't managed to create the PR yet.)
@nikunjgajera I just published @heese PR in version 0.4.5 https://github.com/TheOriginalJosh/nativescript-ngx-slides/pull/43
I'm not sure I follow.
There are changed and finished events you can watch for https://github.com/TheOriginalJosh/nativescript-ngx-slides/blob/master/slides/app/slides/slides.component.ts#L62
link is not valid now. can you share again
This was probably pointing to here: https://github.com/TheOriginalJosh/nativescript-ngx-slides/blob/master/lib/src/slides/slides.component.ts#L62