I'm fairly new to Handlebars so you'll have to excuse my naiveté.
I'm currently working on a Handlebars blog template that utilizes Bootstrap 4 as a CSS framework. For my articles, I would like to iterate through a pattern that repeats itself after the 5th article is displayed on the homepage.
My first article's markup would be the default. Every 2nd and 3rd would use a different block of markup and same with every 4th and 5th.
If you review my code below you will see I am using placeholders for conditionals at the moment (e.g; 'every-2nd & every-3rd'). I am just not sure what I should do here and I haven't been able to find a helper to solve my problem.
<div id="main" class="col-md-8">
{{#each content}}
{{#if every-2nd & every-3rd}}
<div class="col-md-6">
<h4>{{title}}</h4>
<p>{{description}}</p>
<button>{{button_text}}</button>
</div><!-- /.col -->
{{else if every-4th & every-5th}}
<div class="col-md-5">
<img src="{{img_src}}" />
</div>
<div class="col-md-7">
<h4>{{title}}</h4>
<button>{{button_text}}</button>
</div><!-- /.col -->
{{else}}
<div class="col-md-12">
<img src="{{img_src}}" />
<h4>{{title}}</h4>
<button>{{button_text}}</button>
</div><!-- /.col -->
{{/if}}
{{/each}}
Thanks in advance for your time and consideration.
Hello I'll advise you to use a "test" helper that will check for your index loop number.
Handlebars.registerHelper('test', function(lvalue, operator, rvalue, options) {
var doDisplay = false;
var items = (""+rvalue).split("|");
var arrayLength = items.length;
for (var i = 0; (i < arrayLength); i++) {
if (operator == "eq") {
if (lvalue == items[i]) {
doDisplay = true;
}
} else if (operator == "ne") {
if (lvalue != items[i]) {
doDisplay = true;
}
} else if (operator == "gt") {
if (parseFloat(lvalue) > parseFloat(items[i])) {
doDisplay = true;
}
} else if (operator == "lt") {
if (parseFloat(lvalue) < parseFloat(items[i])) {
doDisplay = true;
}
}else if (operator == "le") {
if (parseFloat(lvalue) <= parseFloat(items[i])) {
doDisplay = true;
}
}else if (operator == "ge") {
if (parseFloat(lvalue) >= parseFloat(items[i])) {
doDisplay = true;
}
}
}
if (doDisplay) {
return options.fn(this);
} else {
return "";
}
});
So your code will look like that after using the helper :
<div id="main" class="col-md-8">
{{#each content}}
{{#test #index 'eq' '1|2'}}
<div class="col-md-6">
<h4>{{title}}</h4>
<p>{{description}}</p>
<button>{{button_text}}</button>
</div><!-- /.col -->
{{/test}}
{{#test #index 'eq' '3|4'}}
<div class="col-md-5">
<img src="{{img_src}}" />
</div>
<div class="col-md-7">
<h4>{{title}}</h4>
<button>{{button_text}}</button>
</div><!-- /.col -->
{{/test}}
{{#test #index 'ne' '1|2|3|4'}}
<div class="col-md-12">
<img src="{{img_src}}" />
<h4>{{title}}</h4>
<button>{{button_text}}</button>
</div><!-- /.col -->
{{/test}}
{{/each}}
Let me know in comments if you need more explanations
Related
I am trying to make the weather app in Vite , but when I run the program I get the error "TypeError: Cannot read properties of undefined (reading 'main')". Below is part of the code:
<div id="app" :class="{warm: weather.main && weather.main.temp > 17}">
<main>
<div class="search-box">
<input type="text" class="search-bar" placeholder="Search..." v-model="query" #keypress="fetchWeather" />
</div>
<div class="weather-wrap" v-if="typeof weather.main != 'undefined'">
<div class="location-box">
<div class="location">
{{ weather.name }}, {{ weather.sys.country }}
</div>
<div class="date">
{{ dateBuilder() }}
</div>
</div>
<div class="weather-box">
<div class="temp">
{{ Math.round(weather.main.temp) }}°c
</div>
<div class="weather">{{ weather.weather[0].main }}</div>
</div>
</div>
</main>
</div>
This my js
export default {
name: "app",
date() {
return {
api_key: '803a7cd7089cd54e3ecc37bf1b6a3340',
url_base: 'https://api.openweathermap.org/data/2.5/',
query: 'Taiwan',
weather: {
main: {
temp: 17
}
},
}
my Error
enter image description here
I think the problem is this line:
<div id="app" :class="{warm: weather.main && weather.main.temp > 17}">
If you want to use js within the class="", You just have to prepend it by :, and not wrap it in {}.
Try changing that to:
<div id="app" :class="weather.main && weather.main.temp > 17 ? 'warm' : ''">
This will result in:
either
<div id="app" class="warm">
or
<div id="app" class="">
depending on the condition.
Also, a better way to check for optional properties is to use optional chaining as such:
<div id="app" :class="weather.main?.temp > 17 ? 'warm' : ''">
Below is a snippet of working code.
<script src="https://unpkg.com/vue#3"></script>
<div id="app">
<h1 :class="weather?.main?.temp > 17 ? 'warm' : 'cold'">{{query}}</h1>
</div>
<script>
const {
createApp
} = Vue
createApp({
data() {
return {
api_key: '803a7cd7089cd54e3ecc37bf1b6a3340',
url_base: 'https://api.openweathermap.org/data/2.5/',
query: 'Taiwan',
weather: {
main: {
temp: 18
}
},
}
}
}).mount('#app')
</script>
<style>
.warm {
color: red;
}
.cold {
color: blue;
}
</style>
<div id="app" :class="weather?.main?.temp > 17 ? 'warm' : ''">
<main>
<div class="search-box">
<input type="text" class="search-bar" placeholder="Search..." v-model="query" #keypress="fetchWeather" />
</div>
<div class="weather-wrap" v-if="weather.main != 'undefined'">
<div class="location-box">
<div class="location">
{{ weather.name }}
</div>
<div class="date">
{{ dateBuilder() }}
</div>
</div>
<div class="weather-box">
<div class="temp">
{{ Math.round(weather.main.temp) }}°c
</div>
</div>
</div>
</main>
</div>
export default {
name: "app",
data() {
return {
api_key: '803a7cd7089cd54e3ecc37bf1b6a3340',
url_base: 'https://api.openweathermap.org/data/2.5/',
query: '',
weather: {
main: {
temp: 0
},
},
}
},
I am trying to display the table on my wordpress using days "today, yesterday, tomorrow"
The table "Today" is working fine. But when I click on yesterday or tomorrow Nothing appears.
I need to adjust the buttons well for them to work
This is the code:
<?php $today = new DateTime('today'); $linkmatchs = get_option('link'). $today->format('m-d-y'); $tomorrow = new DateTime('tomorrow'); $linktomorrow = get_option('link'). $tomorrow->format('m-d-y'); $yesterday = new DateTime('yesterday'); $linkyesterday = get_option('link'). $yesterday->format('m-d-y'); ?>
<div class="tab filter-days">
<a class="tablinks yesterday" onclick="openTabs(event, 'yesterday')">yesterday</a>
<a class="tablinks today active" onclick="openTabs(event, 'today')">today</a>
<a class="tablinks tomorrow" onclick="openTabs(event, 'tomorrow')">tomorrow</a>
</div>
<div class="contents widget-content" id="content">
<div id="today" class="tabcontent">
<?php echo strip_tags(do_shortcode('[getthetable url="'.$linkmatchs.'" class="matchesCenter" id="" debug="" tablesorter]')) ;?>
</div>
<div id="yesterday" class="tabcontent">
<?php echo strip_tags(do_shortcode('[getthetable url="'.$linkyesterday.'" class="matchesCenter" id="" debug="" tablesorter]')) ;?>
</div>
<div id="tomorrow" class="tabcontent">
<?php echo strip_tags(do_shortcode('[getthetable url="'.$linktomorrow.'" class="matchesCenter" id="" debug="" tablesorter]')) ;?>
</div>
</div>
<script type="text/javascript">
function openTabs(evt, tabsyName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(tabsyName).style.display = "flex";
evt.currentTarget.className += " active";
}</script>
When I type "fa fa-pencil-square-o" code it works fine, but when I use like class="#Model[i].Icon" the icon is disappearing when I inspect it is showing like "fa fa-pencil-square-o"
#model List<Muksab.Models.AboutModel>
#{
Layout = null;
}
#for (int j = 0; j <= Model.Count(); j++)
{
<div class="row">
#for (int i = 0; i <= 3; i++)
{
if (j <= Model.Count())
{
<div class="col-lg-3 col-md-3 col-sm-6">
<div class="single-about-content">
<div class="icon round-border tran3s">
<i class="#Model[i].Icon" aria-hidden="true"></i>
</div>
<h5>#Model[i].Services</h5>
<p>#Model[i].ServicesDescr</p>
More Details
</div>
</div>
j++;
}
}
</div>
}
I want to create a dynamic div.
I have a list of products which maximum 3 can be in one row "col-xs-4" but if they are 4 products I want 3 with "col-xs-4" and the 4th being with "col-xs-12" to fill the entire row. If I have 5 products I want 3 with "col-xs-4" and the other 2 with "col-xs-6".
I was thinking about depending on the count of the items I set the class
<div class="flippersContainer">
<div class="container">
<div class="col-xs-12">
#{
var children = Model.Content.Children.ToList();
if (children.Any())
{
foreach (var item in children.OfType<RedButtonItem1>())
{
string imagePath = string.Empty;
if (!string.IsNullOrEmpty(item.Image))
{
var itemImage = Umbraco.TypedMedia(item.Image);
imagePath = itemImage.GetCropUrl(80, 160);
}
{
string colCSS = string.Empty;
var productNumber = children.OfType<RedButtonItem1>().Count();
}
<div class="col-xs-4">
<div class="front-two">
<div class="flipperAllFront">
<div class="big-button">
<img class="img-responsive" src="https://www.atlantico.ao/SiteCollectionImages/PARTICULARES/ContaGlobal/Atlantico-Conta-Global-375X178.jpg">
<div class="productTitle">
<span>#item.Title</span>
</div>
<div class="productText">
<span>#item.Description</span>
</div>
#{
if (item.CallToAction != null && item.CallToAction.HasValues)
{
var linkUrl = (item.CallToAction.First.Value<bool>("isInternal")) ? (item.CallToAction.First.Value<int?>("internal").HasValue ? Umbraco.NiceUrl(item.CallToAction.First.Value<int>("internal")) : string.Empty) : item.CallToAction.First.Value<string>("link");
var linkTarget = item.CallToAction.First.Value<bool>("newWindow") ? "_blank" : null;
#:<a role="button" href="#linkUrl" target="#linkTarget">
}
else
{
#:<a class="link-big-button" role="button" data-parent="#accordion" href="##item.Id">
}
#:</a>
}
</div>
</div>
</div>
</div>
}
}
}
</div>
</div>
Thanks in Advance
<div class="col-xs-#(childrenCount==3?"4":childrenCount==4?"3":childrenCount==5?"3":"6")">
<div class="flippersContainer">
<div class="container">
<div class="col-xs-12">
#{
var children = Model.Content.Children.ToList();
int childrenCount = children.OfType<RedButtonItem1>().Count;
if (children.Any())
{
foreach (var item in children.OfType<RedButtonItem1>())
{
string imagePath = string.Empty;
if (!string.IsNullOrEmpty(item.Image))
{
var itemImage = Umbraco.TypedMedia(item.Image);
imagePath = itemImage.GetCropUrl(80, 160);
}
{
string colCSS = string.Empty;
var productNumber = children.OfType<RedButtonItem1>().Count();
}
<div class="col-xs-#(childrenCount==3?"4":childrenCount==4?"3":childrenCount==5?"3":"6")">
<div class="front-two">
<div class="flipperAllFront">
<div class="big-button">
<img class="img-responsive" src="https://www.atlantico.ao/SiteCollectionImages/PARTICULARES/ContaGlobal/Atlantico-Conta-Global-375X178.jpg">
<div class="productTitle">
<span>#item.Title</span>
</div>
<div class="productText">
<span>#item.Description</span>
</div>
#{
if (item.CallToAction != null && item.CallToAction.HasValues)
{
var linkUrl = (item.CallToAction.First.Value<bool>("isInternal")) ? (item.CallToAction.First.Value<int?>("internal").HasValue ? Umbraco.NiceUrl(item.CallToAction.First.Value<int>("internal")) : string.Empty) : item.CallToAction.First.Value<string>("link");
var linkTarget = item.CallToAction.First.Value<bool>("newWindow") ? "_blank" : null;
#:<a role="button" href="#linkUrl" target="#linkTarget">
}
else
{
#:<a class="link-big-button" role="button" data-parent="#accordion" href="##item.Id">
}
#:
</a>
}
</div>
</div>
</div>
</div>
}
}
}
</div>
</div>
I have the following code in this jsFiddle.
The problem I'm having is that my child items do not update properly.
I can Click "Edit User" with a problem and see the data changing, but when I attempt to add a note or even if I were to write an edit note function, the data does not bind properly
http://jsfiddle.net/jkuGU/10/
<ul data-bind="foreach: Users">
<li>
<span data-bind="text: Name"></span>
<div data-bind="foreach: notes">
<span data-bind="text: text"></span>
Edit Note
</div>
Add Note
Edit user
</li>
</ul>
<div id="userModal" data-bind="with: EditingUser" class="fade hjde modal">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>
Editing user</h3>
</div>
<div class="modal-body">
<label>
Name:</label>
<input type="text" data-bind="value: Name, valueUpdate: 'afterkeydown'" />
</div>
<div class="modal-footer">
Save changes
</div>
</div>
<div id="addJobNoteModal" data-bind="with: detailedNote" class="fade hjde modal">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>
Editing Note</h3>
</div>
<div class="modal-body">
<label>
Text:</label>
<input type="text" data-bind="value: text, valueUpdate: 'afterkeydown'" />
</div>
<div class="modal-footer">
Save changes
</div>
</div>
function Note(text) {
this.text = text;
}
var User = function(name) {
var self = this;
self.Name = ko.observable(name);
this.notes = ko.observableArray([]);
}
var ViewModel = function() {
var self = this;
self.Users = ko.observableArray();
self.EditingUser = ko.observable();
self.detailedNote = ko.observable();
self.EditUser = function(user) {
self.EditingUser(user);
$("#userModal").modal("show");
};
this.addNote = function(user) {
var note= new Note("original")
self.detailedNote(note);
$("#addJobNoteModal").find('.btn-warning').click(function() {
user.notes.push(note);
$(this).unbind('click');
});
$("#addJobNoteModal").modal("show");
}
for (var i = 1; i <= 10; i++) {
self.Users.push(new User('User ' + i));
}
}
ko.applyBindings(new ViewModel());
Change this:
$("#addJobNoteModal").find('.btn-warning').click(function() {
To this:
$("#addJobNoteModal").find('.btn-primary').click(function() {
You were targetting the wrong button :)
I think the problem after all was that you must bind to "value:" not "text:" in a form input/textarea.