I am new-ish to jade templates and some of the more complex feature that exist in the templates. As of right now, I am building a mock portfolio site using node and jade. I have a layout that is inherited by all other jade files. The layout has all of the universal site navigation inside of it. I am wanting to highlight what section of the website the user is currently in. I am currently doing this by having a unique js files that will load when the user is in a particular section. This js file will add a class on to the list item in which will add the highlighting to the navigation.
My question, do I need to create and load these js files in order to accomplish this? Is there a better way to get a universal navigation in one template while having a unique highlighter?
If the highlighting does not have functional purposes (e.g. accessibility), or it's done using URI fragments (hashtags), it might be better to leave it to the JS.
If your navigation highlight is per page, you could set it up in nodejs/jade, for example:
app.get('/about', (req, res) => {
var locals = {};
locals.navHighlight = 'about';
res.render('about', locals);
});
And in your jade template you could do something like this:
ul.navigation
li(class=(navHighlight=== 'about' ? 'highlight' : '')) About Me
li(class=(navHighlight=== 'blog' ? 'highlight' : '')) My Blog
Whatever you pass as properties to the locals object of res.render, is available in Jade as variables. And in jade, when using the tag(attr=value, attr2=value,...) format you have access to JS syntax and the exposed variables.
As long as you set a variable (e.g. navHighlight based on which route it enters, you can use that to set the class attribute of the tag. Just make sure to separate the class names with spaces, if you have multiple classes.
Related
I created a blog web application using react and redux and in my blog there is 4 fields id,title,seoName and description and for input in description i am using tiny Mce text editor
Now i want to display the text saved in description field of Blog class which is in HTML
and truncate it using elllipses
This is stored in database
{
"_id" : ObjectId("60640e75f7bafb14f6563d52"),
"title" : "Improve Your Developer Experience With Nuxt Components",
"seoName" : "improve-your-developer-experience-with-nuxt-components",
"description" : "<p><img src=\"https://webconnect-upload.s3.amazonaws.com/160x00u0xj1ny179o3a1fd07kl26/screenshot-from-2021-03-31-11-22-39.png\" alt=\"\" width=\"802\" height=\"274\" /></p>\n<h2 id=\"introduction\">Introduction</h2>\n<p>The Nuxt team has introduced <strong>#nuxt/components</strong> module with the purpose to make Nuxt development faster and to make you, as a developer, more productive. This module comes with amazing features and options that will improve your development experience with Nuxt. No matter if you’re just starting out or an advanced user, #nuxt/components provides a range of options from the simplest setup to advance configurations that will certainly benefit your projects.</p>\n<p>In a nutshell, this module automatically scans, imports and registers Vue components found in the <strong><code>~/components</code></strong> directory, so that we don't have to write import statements when we use them in either pages, layouts or even within components.</p>\n<p> </p>\n<blockquote>\n<p><em>This module parses your template and automatically includes the component in the file where you are using it such as a page, layout or even a component. Because Nuxt.js uses automatic code splitting to split your pages by default this module works perfect as it will only contain the components that are used on that page. Also, if you use a component in more than 2 pages, Nuxt.js will automatically create a shared chunk for them thanks to the magic of WebPack.</em></p>\n</blockquote>",
}
I just want to display only truncated text (removing images from description)
and rest of the things by clicking on read more.
Right now i am using
Suggest if there is any other efficient way
<p className="m-0px truncateBlogDesc"
dangerouslySetInnerHTML={{ __html: e.description }}
></p>
You could use a regex to replace every <img ..> tag in your string (e.description).
For example :
var tmp = inner.replace(/<img .*?>/g,"<text>"); # remove <text> to replace the tag with an empty string
Could you try :
<p className="m-0px truncateBlogDesc" dangerouslySetInnerHTML={{ __html: e.description.replace(/<img .*?>/g,"") }} ></p>
I used this function to do something similar. Maybe it will help you. This function trips all htmls and returns only the texts.
const htmlparser = require('htmlparser2');
function stripTags(html) {
let strippedHtml = '';
// noinspection JSUnusedGlobalSymbols
const parser = new htmlparser.Parser({
ontext(text) {
strippedHtml += text;
},
});
parser.write(html);
parser.end();
return strippedHtml;
};
I have a route for different pages of store profiles in my Node app. Been googling, and I know I can edit the parameters, but I have absolutely no idea how to change the content (loading with React) based on name. I'm just using res.render() to render the specific page.
For example, https://www.instagram.com/adidas shows different content than https://www.instagram.com/nike however, they have the same HTML structure and base profile HTML. It's just the content that is different!
Right now, I just have an store.ejs that is the html structure of each profile.
What's an example for how to change and load content based on the name/id?
Route parameters is probably what you're looking for.
app.get('/:name', (request, response) => {
let locals = {
name: request.params.name,
foo: 'bar'
};
res.render('store.ejs', locals);
});
The local variables can be referenced within your template file.
<h1>Hello <%= name %></h1>
<button><%= foo %></button>
Then navigating to /rohit is going to render a page that contains the following markup.
<h1>Hello rohit</h1>
<button>bar</button>
That said, there are many other ways to build application routes, so it's definitely worth reading the routing docs.
In the client, I know you can use Template.[template name] to reference a specific template.
How could you get a list of all custom meteor templates included in your app that have been created by you (not meteor or included from a package)?
Building on what Richard said, you can check if the property on the Template object is a template like this:
var templates = [];
for(var key in Template){
if(Blaze.isTemplate(Template[key])){
templates.push( key );
}
}
console.log( templates );
You'd probably have to use a specific naming convention for identifying your own templates.
Just do Object.keys(Template). I attached a screenshot from the console.
Basically meteor creates a class called Template. We can iterate over all the keys in the template class.
It may be a very dumb question... I am using Meteor-ui-progress-circle and I want redrawing the template when the percentage (wich is store in a reactive collection Progress) is changed (currently, when I click on a "play" button).
I think I have to use Blaze.render but I don't really understand how it work.
Here a part of my main template (in Jade) :
div.panel-body
div.col-md-9.col-sm-8
p Lorem ipsum...
div.col-md-3.col-sm-4#progress-circle
+progressCircle progress="0" radius="100" class="green"
And my JavaScript :
Template.controlBar.events(
{
"click .play-button": function ()
{
var tmp = Progress.findOne({});
if (!tmp)
{
Meteor.call('createProgress');
tmp = Progress.findOne({});
}
var val = tmp.progressValue;
val += 10;
if (val > 100)
return;
Meteor.call('updateProgess', tmp._id, val);
Template.progressCircle.progress = tmp.progressValue;
Blaze.render(Template.progressCircle, $("#progress-circle")[0]);
},
Doing this... I have several template that are displaying each time I click on the play button. I don't understand how to specify that I don't want a new template but just re-render the one I already have.
Not sure I quite understand your question, but I'll try to help by giving my best understanding of templating and how I have come to use them. If someone sees any incorrect information here, please speak up so I can get a better understanding myself and correct this answer.
First, the Template.XXX.events handlers. In your event handler, you are using a function with no arguments. You can actually accept 2 arguments for these event handler functions: the event and the template. So, you can do something like thus:
Template.controlBar.events({
'click .play_button': function(event, tmpl) {
tmpl.$('div#progress-circle').doSomething();
}
});
Notice the tmpl.$() call? That says to use jQuery to find the specified selector, but ONLY in the current template. This is a wonderful way to use classes to generalize your components, but then be able to filter the selection to only those within the same template...
...Which brings me to my next bit of advice: Use child templates excessively. Any component that I can identify as an "autonomous component" on my page I will consider as a separate template. For instance, I was recently working on a custom reporting page that had a table and some D3 graphs representing some real-time data. In this report page, I had one main template defined for the "page", then each of the D3 graphs where defined as a separate template, and the table was another separate template. This allows several advantages:
Compartmentalization of the "components" of the page, allowing code reuse (I can now put the same graph on ANY page, since it's now an autonomous "component"
The advantage of using the Template.XXX.events trick above to "narrow" the scope of my element searches to elements within that template
Prevents total page refreshes as Meteor is smart enough to only refresh templates that need to be refreshed, which also speeds the responsiveness of the page itself
As a result, I try to apply my Templates liberally. In your case, it would sound to me that if I were to have multiply progress bars on the page that I might turn those into separate templates. I might even do it if I had a single progress bar if it made sense to separate it out for ease of data handling.
Finally, inter-communications between Templates. This can be tricky at times, but the best, most efficient way to do this I have found is through Session variables. The pattern I typically use is to have my data for my template be returned by a Template .helper, which does something like this:
Template.controlBar.helpers({
progressData: function() {
if (!Session.equals('playId', null)) {
return Progress.findOne({_play_id: Session.get('playId')});
}
}
});
Because Helpers are reactive, and Sessions is reactive, the template is re-rendered anytime the 'playId' is altered in the Session. The corresponding Session variable can be set from anywhere in the client code. Again, this tends to work best when you narrow the scope of your templates to the individual components. It is important to note here that the Session object in Meteor is NOT the same as "sessions" in other languages like Java and such, which typically use cookies and a session token/id. Meteor sessions work considerably different, and do not survive page reloads or closing of browsers.
I'm currently reusing a template to populate a list using the code below:
<li>
{% include "ding/search_result.html" with title=field.title url=field.url description=field.description %}
</li>
When new data comes in, I want to be able to add new elements to my list dynamically from javascript. I can use the code below to add new list items:
$("ul.search-results-list").append('<li>New List Item</li>')
Is there a way for me to append the reusable template code I'm using, and pass in the appropriate parameters?
Yes there is! AND you get to refactor your APIs as well.
Imagine that you have an API that returns this json blob for every new list item.
{
name: "limelights"
}
And let's just use jQuery for this (even though I kinda don't want to.)
So you query the API like this
$.getJSON('api/v1/getName.json', {'someParameter', 123}, function() {
//this is where you would do your rendering then.
});
So how to do the rendering? Well, I'm a huge fan of underscore.js and it's rendering of templates, so I'm gonna go ahead and use that (but you can exchange it for Mustasche, Handlebars, Hogan or whatever you fancy).
First, we'll define a script template like this: (We're using underscore.js own ERB style template language).
<script type="text/template" id="my_fancy_list">
<li><%= name %></li>
</script>
Now this can live pretty much anywhere, either in your template or you can require it in if you're using Require.JS but we're gonna assume that it lives in your template (Hint: it could be rendered by some Django template tag)
Anyhoo,
Fill this template with data now:
var template = _.template($('script#my_fancy_list').html());
//this will give you the template as a javascript function.
//Query the API
$.getJSON('api/v1/getName.json', {'startsWith': 'l'}, function(data) {
$('ul.search-results-list').append(template(data));
});
And presto, you now have an JavaScript driven application that renders new data that comes from the server without fetching the entire template and render it all again.