I'm trying to create a html template for displaying posts via html/template Go package.
I also want to make pagination on my page, to display 5 posts per page.
So I take the post count from my post repository, dividing it by posts per page value and rounding it (ceil). That's the total number of pages with posts currently available.
I pass the total number of pages to my html template.
Now, in my html template I need to display page buttons from 1 to the total number.
In the text/html package there is an awesome documentation about how to work with pipelines, but I didn't find any example of creating simple loop.
I got the solution, but I am not sure it is the good one.
I can pass to template not just the total number of pages, but an array of available pages, so in my template I can do something like:
{{range .pages}}
<div class="page">{{.}}</div>
{{end}}
But maybe there is a better way to do this than passing an array of pages?
I also know about possibility of passing custom functions to template. Could it be a solution?
The rule is that the template must contain the minimal logic possible (and that's the reason why the native functions and controls are so limited into the template package).
You should prepare your data into the controller by putting it into a dedicated struct (to be passed to the template). Then you can display this struct (composed of variables and arrays) into the template by using the range function as you intended to do.
try this, i have do my best...
package main
import "html/template"
import "os"
type data struct {
Url string
Title string
}
type show struct {
Pages []data
}
const html = `<html>
{{range .Pages}}
<div class="page">{{.Title}}
</div>
{{end}}
</html>`
func show_template() {
webpage, _ := template.New("template").Parse(html)
mydata := []data{{
Url: "page-1.html",
Title: "go to page 1",
}, {
Url: "page-2.html",
Title: "go to page 2",
}, {
Url: "page-3.html",
Title: "go to page 3",
}, {
Url: "page-3.html",
Title: "go to page 3",
}}
web_data := show{mydata}
webpage.Execute(os.Stdout, web_data)
}
func main() {
show_template()
}
and this is the result..
<html>
<div class="page">go to page 1</div>
<div class="page">go to page 2</div>
<div class="page">go to page 3</div>
<div class="page">go to page 3</div>
</html>
Related
I am working on some project, i want to return filtered data to some new page, what i am facing right now is, that output is shown on same template, so lot of extra stuff occurs which i do not want. I want to redirect it using router, but this filter function is a part of images_thumbnail.
Client > main.html
<template name="images_thumbnail">
//lot of stuff + images
{{#each images}} //show all images from public folder
<img src=""some_image.jpg" alt="img_title" />
<caption>
<a href="#" class="js-set-genre-filter">
{{img_genre}} //image_genre associated with this image
</a>
</caption>
{{/each}}
</template>
When I click image genre (say Thriller, Comedy, etc.), image filter is set
Client > main.js
Router.route('/images', function(){
this.render('navigation_bar',{
to: 'header'
});
this.render('owl_carousel', {
to: 'carousel'
});
//images_thumbnail template along with navbar, carousel
this.render('images_thumbnail', {
to: 'body'
});
});
Tempalte.images_thumbanil.events({
'click .js-set-genre-filter':function(event){
Session.set("genreFilter", this.img_genre);
console.log(this.img_genre); //gives Comedy/Thriller
}
})
Template.images_thumbnail.helpers({
images:function(){
if(Session.get("genreFilter"))
return Images.find({img_genre: Session.get("genreFilter")};
//This is the output, but i want to redirect it to some
//new template, instead of images_thumbnail template
}
})
When no filter is set
Output when no Filter is set, Navigation bar, Carousel, rest stuff is visible
Filter output, when genreFilter is set
Navigation bar, button, Headings are shown which are not needed for this content
I don't think I understand fully what you want,
if you want to redirect your route to another at the point of your code,
simply use Router.go('/newPath')
In addition,
Iron router was great package still,
but Meteor Developer Group(MDG) and a lot of people changed to use FlowRouter
because of maintanence and to focus on routing itself. (Iron Router controls pub/sub and lifecycle too much.)
So consider to FlowRouter too-
I have the following Meteor template:
<template name="homeBoxTpl">
<div>
Some content
</div>
</template>
I have an event binding so that when a button on the page is clicked it should get the html contents of the template "homeBoxTpl" - how can this be achieved?
What you need is an event handler, and like Chase say you can access the content of meteor templates using jquery, but meteor has its own way. In order to get a copy of the html, you can place a wrapper round the content in the template, then do this:
Template.homeBoxTpl.events({
'click #someButton':function(e,t){
var templateContents = t.$('.wrapperInTemplate').html();
}
})
Here we are using Template.$ wich returns a jQuery object of those same elements.
Take a look into Template.instances for more information
Just to clarify, where is the button? Is it in another template? I assume you only render homeBoxTpl once.
In which case the event handler for the template where your button exists will have no reference to another template instance. There is no global lookup where you can find all rendered instances of a specific Template
You will have to set an unique identifier "id" for it, or some other discerning info such as a class/attribute and find it via old fashioned JS DOM selectors/traversal.
document.getElementById is fastest, but if there are multiple instances of that template, t.firstNode does give you a good starting point for the DOM traversal.
However making your code dependent on a specific DOM layout is bad practice / too much coupling. Is there any reason why the data underlying that Template's HTML content isn't available somewhere else like a session or collection? It would perhaps be more flexible too to access the data not the HTML.
You can use jquery to access what you need. For example, if you have the following template:
<template name="homeBoxTpl">
<div class="content-container">
Some content
</div>
<button id="btn" type="button">Click me</button>
</template>
Then use the following javascript:
Template.homeBoxTpl.events({
'click #btn': function(e) {
e.preventDefault();
var content = $(".content-container").text();
console.log(content); //Result is "Some content"
}
});
I am trying to access a DOM element corresponding to the particular template instance that is calling a helper function. As I read the Meteor documentation, Template.instance() should return the template instance object that called the helper, and something like Template.instance().$() would allow me to grab DOM elements within that instance.
However, the following code (and similar variations) is not working for me:
* HTML *
<template name="input_container">
<div class="small-12 medium-12 large-6 columns empty {{isActive}}"></div>
</template>
* JS *
Template.input_container.helpers({
isActive: function() {
if (Template.instance().$('.empty') && [some Session variable logic] {
return 'active';
}
}
});
When I do something like:
if (some Session logic) {
console.log(Template.instance())
}
I get the helper properly logging multiple versions of:
Blaze.TemplateInstance {view: Blaze.View, data: 7,
firstNode: div.small-12.medium-12.large-6.columns.empty.active-container,
lastNode: div.small-12.medium-12.large-6.columns.empty.active-container, $: function…}
(With data: values going from 1-12 appropriately, but otherwise each seems to be the same)
How do I get from this to being able to used the template methods such as template.$ or template.find?
EDIT:
While not a perfect solution, I did manage to work around some of these issues by using Template.currentData() and setting an identifier on each instance of the input.
Template.create_form.helpers(
# Create 12 input containers
inputContainer: () ->
[0..11]
And then:
Template.input_container.helpers(
isActive: () ->
# Get which template instance we are working with, will return the number 0-11 that was used to create it
current = Template.currentData()
# Now I can do $(".input-container").eq(current) to grab the correct DOM element
)
But it seems a little dirty to need to use so much jQuery.
I'm not sure if I've interpreted the question correctly, but if you're trying to access another DOM element on the page - I was able to use a jquery selector.
For example, given html of
<input type="textfield" id="initials" value=" ">
and a simple meteor template of
<template name="demo">
<input type="button" div id="s0">
</template>
I can successfully access the initials field when the s0 button is clicked as follows
Template.demo.events({
'click .cell': function(event, template) {
if ($('#initials').val().trim().length > 0) {
console.log($('#initials').val().trim() + ' - you clicked button '+$(event.target).attr('id'));
}
},
In my meteor project, I have added iron:layout, iron:dynamic-template along with iron:router.
My question is, how can you prevent the dynamic template from rendering if there is no data available in the Session? The reason is, the dynamic template is currently being rendered with all html content within it except for data context. This is the problem when the user initially arrives onto the page.
I have a list of names on 'postlist' template. These are 'usernames' of the person who created the post. When a user clicks on the name, the template 'viewpost' is rendered with the relevant data passed...that is fine. But as stated earlier, there is no data context when the user first arrives onto the page. So the see all the content except for the dynamic content.
The following is my current code, with help received from my previous post. Meteor: Render template inside a template
HTML:
<template name="postlist">
<div class="container">
<div class="col-sm-3">
{{#each post}}
<li>{{fullname}}</li>
{{/each}}
</div>
</div>
{{> Template.dynamic template='viewpost' data=currentPost}}
</template>
Click event to capture post _id / helper file:
Template.postlist.helpers({
currentPost: function(){
return Posts.findOne(Session.get('currentPost'));
}
});
Template.postlist.events({
'click li': function(e){
e.preventDefault();
Session.set("currentPost", this._id);
}
});
This is one alternative hack method but understand is not good practice. This is what I am effectively wanting to achieve so you get an idea. But I would like non-hack suggestions for this issue. Thank you.
html:
<template name="viewpost">
{{#if hasData}}
<div class="container">
Post creator is : {{username}} - Info: {{body_text}}
</div>
{{/if}}
</template>
js:
Template.viewpost.helpers({
"hasData":function(){
return Session.get("currentPost");
}
});
I have a functioning Knockout template for some pagination UI that works with a Knockout-based shared data grid. This template renders an HREF for each "page" of data in the grid.
The template works but it's klunky because if I fetch a lot of data, then I end up with dozens and dozens of navigation page links below the grid. Here's the current template:
<div class="idTemplate_ko_simpleGrid_pageLinks">
<p>
<span>Go to page:</span>
<!-- ko foreach: ko.utils.range(0, maxPageIndex) -->
<a href="javascript:void(0);"
class="grid-pagination"
data-bind="text: $data + 1, click: function() { $root.currentPageIndex($data) }, css: { selected: $data == $root.currentPageIndex() }"></a>
<!-- /ko -->
</p>
</div>
The 'currentPageIndex' value is just a simple ko observable in the model:
this.currentPageIndex = ko.observable(0);
And 'maxPageIndex' is a computed observable in the model:
this.maxPageIndex = ko.computed(function () {
return Math.ceil(ko.utils.unwrapObservable(this.filteredItems()).length / this.pageSize()) - 1;
}, this);
How can I modify the template and model to enable paging UI similar to StackOverflow?
For example:
prev 1 ... 3 4 5 6 7 ... 69 next
This is exactly the pager style I have been using for a while now.
I just finished extracting the pager functionality I used on several projects, into an extension to knockout and template by example.
See https://github.com/remcoros/ko.pager for the source and http://remcoros.github.com/ko.pager/example.html for a working example.
All computations and some convenient properties are provided by the 'Pager' class, which you can create and bind to. But an example working template is included.
See the source example.html for usage.
First thing I would do is look if there are any custom bindings or libraries out there that do this. If there are, create a custom binding that uses that library.
Back up plan - make your own custom binding.
I'd make something like:
<div data-bind="pagination: { maxIndex: maxPageIndex(), numToShow: 7 }">
...
</div>
Then in my custom binding, do something like this:
ko.bindingHandlers.pagination = {
update: function(element, valueAccessor) {
if (valueAccessor().maxPageIndex > valueAccessor().numToShow) {
// use jquery to loop and append new $("<a>") tags to $(element), using "1", then ... and a segment in the middle, followed by ... and the last index.
}
else {
// loop over the regular amount.
}
}
};
Im so nice so I made one for you in exactly two minutes :P (So it probably has bugs)
Its based on the first pager i found which was jQuery pagination
http://jsfiddle.net/tymTz/2/