SwiperJS, Blade Laravel: How to dynamically create a new swiper from inside a #foreach loop inside a BLADE template? - laravel-blade

I have a #foreach loop, where each item inside the loop is a "row" representing a carousel (SwiperJS ) instance. If there are 1, 2, or 3, I can just manually initialize the swiper instance in the JS section with
JS
var swiper1 = new Swiper(".swiperA", { ...}
var swiper2 = new Swiper(".swiperB", { ...}
var swiper3 = new Swiper(".swiperC", { ...}
...
var swiper26 = new Swiper(".swiperZ", { ...}
HTML BLADE
#foreach($rowItem as $rI => $row) {{ROW x-dim}}
<div class="swiper swiperA menu-wrapper">
<div class="swiper-wrapper">
#foreach($var as $key=>$variables) {{imgs in each ROW y-dim}}
<div class="swiper-slide">
<image src="$var->img_link" alt="image">
</div>
#endforeach
</div>
</div>
#endforeach
How do I dynamically generate a carousel (SwiperJS) instance for each row?
not using VUE, or REACT.
There might be 1 row (1 swiperJS instance), or there might be 10 rows (SwiperJS instances).
LAYOUT OF PAGE
based on the number of items in $row from #foreach loop
Thanks,
Cindi

Related

Getting Children recursively for a treeview generation in a template

Here is how my structure is setup:
I have many Services (DocType) which hold children Documents (DocType).
The Document DocType can have other Document elements as its children.
This way, it's possible for editors to create that kind of tree:
Service > Document> Document >Document > Document
There's no limits to the amount of levels this can go on for.
I'm trying to find a way to loop recursively through each Document and their descendants, but they need to be nested within eachother. This is where I'm having trouble.
I can't seem to find a simple way to loop recursively through each levels per children to generate the content.
Here is what I have so far:
#{ var selection = Model.Children.Where("Visible");
if (selection.Any()) {
<ul>
#foreach (var item in selection) {
<li>
<div class="ServiceDocCenterDocumentation">
<h4>#item.Name</h4>
<div class="DocCenterDocumentationDescription">#item.GetPropertyValue("bodyText")</div>
</div>
<div>
#foreach (var children in item.Descendants()){
#* This is the part I'm struggling with for the last few days *#
var actualChildren = children;
<h5>#children.Name</h5>
<div class="DocCenterDocumentationDescription">#children.GetPropertyValue("bodyText")</div>
}
</div>
</li>
}
</ul>
}
}
Here's what I would like to achieve (recursively, not manually):
<div class="myService">
<div class="Documents">
<div class="Document_#elem.Id">
#elem.bodyText
foreach (var child in elem.Children){
<div class="Document_#child.Id">
#child.bodyText
foreach (var grandchild in child.Children){
#* It goes on and on for the amount of levels available *#
}
</div>
}
</div>
</div>
</div>
I'm still not very fluent in Razor, and I'm wondering if there's a way of achieving what I would like to achieve.
You should use Razor helpers to create your recursive function.
Apart of that, you shouldn't use Descendants in each children as it would return every node below this one. You just need its children, then the children of each children and so forth. So you will pass each children list to the function to display it.
#{ var selection = Model.Children.Where("Visible");
if (selection.Any()) {
<section class="DocCenter">
#foreach (var item in selection) {
<section class="Service">
<div class="ServiceDocCenterDocumentation">
<h1>#item.Name</h1>
<div class="DocCenterDocumentationDescription">#item.GetPropertyValue("bodyText")</div>
</div>
#DisplayChildren(item.Children().Where("Visible"))
</section>
}
</section>
}
}
#helper DisplayChildren(IEnumerable<IPublishedContent> children){
if(children.Any()){
<section class="children">
foreach(var child in children){
<section class="Document_#child.Id">
<div class="DocumentDetails">
<h1>#children.Name</h1>
<div class="DocCenterDocumentationDescription">#children.GetPropertyValue("bodyText")</div>
</div>
//Recursive call here
#DisplayChildren(child.Children().Where("Visible"))
</section>
}
</section>
}
}
On the other hand, although is not related to the recursive question, I would use the <section> element to separate parents and children, that way you can also use h1 for all the headings as they are created in a section hierarchy:
Using HTML sections and outlines

convert from foreach to for loop

below code working perfectly . but i need to convert it from foreach to for loop .please help me to iteration by for loop. because i have to introduce some if else statement in entire code
#foreach (var item in ViewData["productSl_1"] as IEnumerable<Nazmulkp.Models.Product>)
{
<div class="col-md-3 ">
<div class="thumbnail">
<img src="#Url.Content(item.ImagePath)" alt="Image" style="max-width:100%;">
<div class="caption">
<h5>#item.ProductName</h5>
<h4>Tk.#item.Price</h4>
</div>
</div>
</div>
}
Example:
I have to make sure if index number 2 than execute <div class="col-md-3>"
Thank you
You do not need to convert your foreach to a for loop for adding a conditional css class. Simply add a counter variable to your code and use that for your if condition as needed.
For example, the below code will add the css class "col-md3" to the 3rd item in your collection.
#{ var counter = 0;}
#foreach (var item in YouCollectionHere)
{
<div class="#(counter==2?"col-md-3":"")">
<h2>#item.Name</h2>
</div>
counter++;
}

MeteorJS and Packery layout doesn't re-render when collection is updated

I'm integrating MeteorJS collection with Packer for a Pinterest-like interface.
I'm having an issue that when a new item is added to the collection which is rendered by Packery (or Masonry, same issue), the new item just floats on top left of the container, and is not run through the Packery layout processor.
triggerMasonryLayout = function () {
var $container = $('#masonry-layout');
console.log("AUTORUN PACKERY", $container);
$container.packery({
itemSelector: '.item',
gutter: 20,
columnWidth: 300
});
$container.packery();
}
Template.bookingsProfileItem.onRendered( function() {
triggerMasonryLayout();
});
<template name="bookingsProfileItem">
<div class="item">
...
<div id="masonry-layout">
{{#each properties}}
{{> bookingsProfileItem}}
{{/each}}
</div>
I just figured out the solution to this problem and the key is _uihooks! This will invoke the functions you want after the change in the collection and before Blaze reactively update the DOM.
Not sure why you mixed Masonry and Packery into one. My solution here is strictly Packery.
bookingsProfileItem.js
var triggerPackeryLayout = function () {
var $container = $('#packery-layout');
$container.packery({
itemSelector: '.item',
gutter: 20,
columnWidth: 300
});
}
Template.bookingsProfileItem.onRendered(function() {
this.find('#packery-layout')._uihooks = {
//when new items are added to collection
insertElement: function(node, next) {
triggerPackeryLayout();
$('#packery-layout').append(node);
$('#packery-layout').packery('appended', node);
}
}
});
bookingsProfileItem.html
<template name="bookingsProfileItem">
<div class="item">
{{...}}
</div>
</template>
<div id="packery-layout">
{{#each properties}}
{{> bookingsProfileItem}}
{{/each}}
</div>
Got my references from RainHaven's Meteor UI Hooks Demo:
https://github.com/RainHaven/meteor-ui-hooks-demo/blob/master/simple-todos.js
Meteor's v1.0.4, 2015-Mar-17 documentation on uihooks:
https://github.com/meteor/meteor/blob/master/History.md#blaze-2

Template helper crashing app

My app is crashing my browser after implementing this columnWidth helper method. All I'm trying to do is rotate between col-md-7 and col-md-5 (Bootstrap classes) so that no two consecutive posts are the same width.
columnWidth: function() {
if (Session.get('columnWidth') === 'col-md-7') {
Session.set('columnWidth', 'col-md-5');
} else {
Session.set('columnWidth', 'col-md-7');
}
return Session.get('columnWidth');
}
The post template:
{{#each this}}
<div class="{{columnWidth}}">
<img src="{{image}}" height="350" width="{{imageWidth}}" alt="">
<div class="content">
<h2>{{title}}</h2>
<p>{{content}}</p>
<span class="dateAuthored">{{date}}</span>
</div>
</div>
{{/each}}
this refers to:
data: function() {
return Articles.find();
}
Any ideas why this is happening? I'm not receiving any errors. The browser tab just becomes unresponsive. Thanks.
You are constantly setting the same reactive variable so for example with the first div when the helper is called it will set it to col-md-7, then when it is called for the 2nd row you are changing the same variable to col-md-5 which is problematic for 2 reasons:
a) the template will redraw the first column and so they will both be col-md-5
b) the same helpers will get called again. I believe your browser crashes because you have created an infinite loop. Try console logging something inside your columnWidth helper and see how many times it gets called.
To achieve what you want you need to get the index of the {{#each }} loop and then have the column class dependent on whether it's odd or even. Unfortunately getting the index in meteor handlebars is a little tricky.
Try:
{{#each articles}}
<div class="{{columnWidth index}}">
<img src="{{image}}" height="350" width="{{imageWidth}}" alt="">
<div class="content">
<h2>{{title}}</h2>
<p>{{content}}</p>
<span class="dateAuthored">{{date}}</span>
</div>
</div>
{{/each}}
Then the following helpers:
articles: function() {
//'this' in this context should work.
//if not just replace with Articles.find().map(...
var articles = this.map(function(article, index) {
var i = _.extend(article, {index: index});
return i;
});
return articles;
},
columnWidth: function(index) {
if (index % 2 === 0)
return "col-md-5";
else
return "col-md-7"
}

NopCommerce - Category Images not displaying

I can't get category images to display in a NopCommerce theme. This is the code I'm using, on the CategoryTemplate.ProductsInGridOrLines.cshtml page.
#if (Model.PictureModel != null && !String.IsNullOrWhiteSpace(Model.PictureModel.ImageUrl))
{
<div class="category-picture">
<img alt="#Model.PictureModel.AlternateText" src="#Model.PictureModel.ImageUrl" title="#Model.PictureModel.Title" />
</div>
}
I've tried removing the if statement, and it just generates <img>.
as far as i am aware, category images should be accessed like this..
#foreach (var item in Model.SubCategories)
{
count3++;
<div class="sub-category-item col-4 alignCenter">
<h2 class="title">
<a href="#Url.RouteUrl("Category", new { SeName = item.SeName })" title="#item.PictureModel.Title" class="green">
#item.Name</a>
</h2>
<div class="picture">
<a href="#Url.RouteUrl("Category", new { SeName = item.SeName })" title="#item.PictureModel.Title">
<img alt="#item.PictureModel.AlternateText" src="#item.PictureModel.ImageUrl"
title="#item.PictureModel.Title" /></a>
</div>
</div>
if (count3 %3 == 0)
{
#Html.Raw("</div><div class='row'>")
}
}
this is a slightly modified version of the original nopcommerce code in a site i'm currently working on and this code works.
note that images are taken from the item.pictureModel rather than Model.PictureModel.
this is assuming that you have not moved this code into a separate file.
hope this helps
Before using your code you should add the following code to the Category method in the CatalogController:
//prepare category picture model
int picId = category.PictureId;
int picSize = _mediaSettings.CategoryThumbPictureSize;
var categoryPicCacheKey = string.Format(ModelCacheEventConsumer.CATEGORY_PICTURE_MODEL_KEY, model.Id, picSize, true, _workContext.WorkingLanguage.Id, _webHelper.IsCurrentConnectionSecured(), _storeContext.CurrentStore.Id);
model.PictureModel = _cacheManager.Get(categoryPicCacheKey, () =>
{
var pictureModel = new PictureModel()
{
FullSizeImageUrl = _pictureService.GetPictureUrl(picId),
ImageUrl = _pictureService.GetPictureUrl(picId, picSize),
Title = string.Format(_localizationService.GetResource("Media.Category.ImageLinkTitleFormat"), model.Name),
AlternateText = string.Format(_localizationService.GetResource("Media.Category.ImageAlternateTextFormat"), model.Name)
};
return pictureModel;
});`

Resources