Is it possible to dynamically add a slide to an existing Materialize Carousel? - materialize

I am able to create a carousel as described here. The carousel appears and works properly.
Later on I would like to add an additional slide:
$(".carousel").append('<a class="carousel-item active" href="#six!"><img src="http://lorempixel.com/250/250/nature/6"></a>');
However, this does not appear to work as the slide does not get added to the carousel.
Is adding slides to an initialized carousel not supported or is this an issue on my end?

Sure it is. I haven't seen any solution in the internet. I believe that there might be a better and smoother solution but this one is mine.
All you need to do is after adding your new items remove the initialized class from already initialized main carousel div and reinitialize it.
//init carousel
var slider = $('.carousel');
slider.carousel();
//add a new item
slider.append('<a class="carousel-item active" href="#three!"><img src="http://lorempixel.com/250/250/nature/3"></a>');
//remove the 'initialized' class which prevents slider from initializing itself again when it's not needed
if (slider.hasClass('initialized')){
slider.removeClass('initialized')
}
//just reinit the carousel
slider.carousel();
full working fiddle: https://jsfiddle.net/8tq4ycm3/

I had the same problem, but I'm using the slider. (http://materializecss.com/media.html#slider)
To resolve this, it was necessary to clear all items, re-add items with the new one, and then re-bind the slider.
Follow example: https://codepen.io/troits/pen/QvdZov
let itens = [];
function addItem(){
$('.slides').empty();
$('.slider > .indicators').detach();
itens.push(createItem());
for(i in itens){
$('.slides').append(itens[i]);
}
$('.slider').slider();
showItem(i);
}
function showItem(i){
$('.slider > .indicators > .indicator-item')[i].click();
}

Related

zooming the page will reset the carousel

Is there a way to avoid reset the carousel after the user zoom in/out the browser page?
I found pages with similar carousel and this behaviour doesn't happens.
Go to spartacus demo website https://spartacus-demo.eastus.cloudapp.azure.com/electronics-spa/en/USD/, in the carousel navigate to the next block of slide, then zooming the page, you should see the carousel reset to the first block of slides.
This behaviour of the CarouselComponent is expected. Its service depends on window.resize event to adjust the number of items on carousel page whenever the window got resized.
If you consider it as a bug, please create an issue in the Spartacus GitHub repository. Team will take your proposal into consideration.
There is one way this can be handled.
In DOM, instead of using Spartacus's activeSlide variable for rendering the UI, use one tempVariable named say tempActiveSlide
Reassign the tempActiveSlide only if the items per slide are changing. This count will change whenever the window resizes and which is as per the functionality of CarouselService.
Ref - https://sap.github.io/spartacus/injectables/CarouselService.html#source
This way, the carousel on UI will only reset if the number of items per slide have changed. Otherwise it wont reset.
TS code:
tempActiveSlide;
itemsPerSlide = 0;
ngOnInit(): void {
super.ngOnInit();
this.tempActiveSlide = this.activeSlide;
this.size$.subscribe((items) => {
if (items !== this.itemsPerSlide) {
this.itemsPerSlide = items;
this.tempActiveSlide = this.activeSlide;
}
});
}

Vue lazyloading gets triggered when adding dynamic class to <main>

I am adding a 'sticky-header' class to my dynamically, but when its sticky i obviously also need to add padding to my so the content doesnt go behind the header.
The problem is that when adding the padding via class-binding(v-bind:class="{'fixed-header': stickyHeader}")on scroll, this reloads all the lazy-loaded images (that are lazy loaded using vue lazy)
This makes all images go from loading to loaded in a split second, but its very noticable.
stickyHeaderis a boolean that gets recalculated on scroll, if the window is scrolled past a certain element (with a eventlistener on scroll: checkHeader())
checkHeader() {
var elementTarget = document.getElementById("notice");
if(window.scrollY > (elementTarget.offsetTop + elementTarget.offsetHeight)){
this.stickyHeader = true;
}
else{
this.stickyHeader = false;
}
}
Anyone know what exactly triggers the images to go back to 'loading' for a split second?
To solve this instead of dynamically binding the class with v-bind i simply add it in the scroll listener method with basic javascript, now it doesnt rerender :) !

Dojo grid inside titlePane not getting painted until the browser is resized

I have an dojo enhanced grid inside a title pane which inturn in Tabcontainer. I am creating a tab container dynamically and painting the title pane which contains grid. For the first time the grid is painted properly but if i close the tab and again try it to open a tabcontainer title pane is painted but grid inside the titlepane is not painted (or rather its not visible) until i do a browser resize.
So anybody have faced similar kind of issue? Please let me know the solution for this.
I tried resize(), update() & startup() methods on grid nothing worked out.
I am kind of stuck please share your thoughts on this.
Thanks,
Vikram
I had the same problem and found a workaround by doing a dojo connect like:
dojo.connect(Datagrid,"_onFetchComplete",DataGrid,"_resize");
So it should automatically be resized, when DataGrid finished loading data.
Hope I could help.
Greeting, Simon
Have you tried setting an absolute height on the Grid?
Which browsers did you try? (I experienced various problems with DataGrid in TabCointainer using IE)
You must call the TabContainer.layout() each time its container is changing size. For doing this, you could 1) monitor DOMEvents onunderflow and onoverflow on containing DOMNode or 2) when container becomes visible (once-n-forall).
Reason why a window.onresize event fixes it is, that the TabContainer hooks on said event and calls its own layout.
In your situation, where the TabController fiddles with TabContainer's panes, there may be missing a 'layoutChildren' somewhere. Optimally, you should place the grid as the first on only child to tab.
After the grid is deployed, it will take an absolute, calculated height - 'inherited' from the TabContainer. This is fired once the TabContainer chooses to resize or instructed to do so.
Manually, you should be able to implement these lines - after re-opening a tab. The script is taken from _Grid.js to illustrate
var grid = dijit.byId('MYGRIDID');
require(["dijit/layout/utils"], function(layerUtils) {
layoutUtils.layoutChildren(grid.domNode,
grid._contentBox,
[grid.tablist, {
domNode: grid.tablistSpacer,
layoutAlign: titleAlign
}, {
domNode: grid.containerNode,
layoutAlign: "client"
}]);
grid._containerContentBox = layoutUtils.marginBox2contentBox(grid.containerNode,
{
domNode: grid.containerNode,
layoutAlign: "client"
});
// note this line in particular
grid.selectedChildWidget.resize(grid._containerContentBox);
}
My issue
I had a similar situation as yours:
Grid is in a titlepane (closed by default).
Grid can be destroyed and re-created on the fly.
Issue appears when user:
opens the pane.
closes the pane.
re-creates the grid.
re-opens the pane.
grid is not visible, until browser window is resized!
My solution
My approach was to force a resize() on my grid whenever the title pane was being opened.
I used code like this, in a place where I had access to both the grid and the panes:
var titlePane = registry.byId("title-pane-id");
var handle = aspect.after(titlePane, "toggle", function(deferred) {
if (titlePane.open) {
grid.resize();
}
});
The dojo/aspect doc
Don't forget to remove the aspect from your grid if you destroy it.
I did this on dojo v1.8.1
My solution is too easy: define on declaration of grid the bold parameter write here:
grid = new EnhancedGrid({id: 'MyIDgrid',
store: dataStore = new ObjectStore({objectStore: myStore}),
structure: structureGrid,
plugins: pluginGrid,
style : 'width: 725px; height: 350px',
autoWidth : true,
**autoHeight : false,height:'200px',**
elasticView : '2'
}, document.createElement('div'));
this resolve all!
Enjoy!
style="height: auto;" will fit the purpose.

DojoX Mobile ListItem load HTML via AJAX and then remove from DOM

Let's say in a view I have a DojoX Mobile ListItem that is pulling an HTML view fragment into the DOM via AJAX and then transitioning to that view. Assume this is all working fine.
Now, I go back to the initial view that had that ListItem on it and click some other button that destroys that view node from the DOM. If I now click on that ListItem that previously loaded that view node into the DOM (which has now been removed), it will try to transition to a view that doesn't exist. It doesn't know that it has been removed.
Is there some type of way to tell a ListItem that it needs to fetch the HTML again because what was previously fetched no longer exists? I am not seeing anything about doing this in any documentation anywhere. I don't think a code sample is really necessary here, but I can provide a minimal one if necessary.
I went a different route and left the view exist in the DOM, and simply made a function that clears all sensitive data out of the view.
Okay, in this case, i guess you could hook the onShow function of your ListItem container(or any other onchange event). Create a listener for said handle to evaluate if your item needs reloading. Following is under the assumtion that it is the item.onclick contents showing - and not the label of your item which contains these informations
Or better yet, do all this during initialization so that your ListItem container will be an extended with custom onClick code.
Seems simple but may introduce some quirks, where/when/if you programatically change to this item, however here goes:
function checkItem() {
// figure out if DOM is present and if it should be
if( isLoggedIn() ) {
this.getChildren().forEach(function(listitem) {
if( dojo.query("#ID_TO_LOOK_FOR", listitem.domNode).length == 0 ) {
// this references the listItem, refresh contents.
// Note: this expects the listitem to be stateful, have no testing environment at time being but it should be
listitem.set("url", listitem.url);
}
});
}
}
Preferably, set this in your construct of the container for your ListItems
var listItemParent = new dojox.mobile.RoundRectList({
onShow : checkItem,
...
});
Or create listener
var listItemParent = dijit.byId('itemRegistryId');
// override onClick - calling inheritance chain once done
dojo.connect(listItemParent, "onClick", listItemParent, checkItem);

Reload carousel items

I need to reload the items from my carousel (I clicked on an item and a panel gets destroyed, then when I try to go back, I need to rebuild the carousel)
For this I am removing the items of the carousel by doing:
var len = cards.length;
for(var c = 0; c < len;c++)
this.myCarousel[0].items.remove(cards[0]);
then I set the cards again and set the carousel items again:
this.myCarousel[0].items.append(cards);
this.doLayout();
but after doing this, the cards dont get set right, they just get written on top of each other, no carousel effect gets done. Also the cards start being drawn under the carousel's toolbar, instead of starting below the toolbar.
The first time when I load the cards it works perfectly (when I build the carousel from scratch), but if I delete the previous cards and add them again, they don't get displayed properly, I hope someone can help me.
Thank you in advance
Do the adding and removing on the carousel itself as it has methods to do this:
this.myCarousel.removeAll();
var items = [];
for (...) {
items.push(<item def>);
}
this.myCarousel.add(items);
this.carousel.doLayout(); // Force the carousel to re-render
this.myCarousel.scrollToCard(0); // This will send the user back to the first card
If the user was at a different card when you run the above (say, if you put this into an orientation check) then you should return them to the correct card like so:
var curIndex = this.myCarousel.items.items.indexOf(this.myCarousel.layout.activeItem);
// Now do removing and adding
this.myCarousel.scrollToCard(this.myCarousel.items.items[curIndex]);
You have to use the index as the item will be removed.
id should only be used for debugging. There are better ways to resolve a component than use id that can get you into trouble.