I registered it
handlebars.registerPartial('nav', 'view/partials/nav');
And I called it
{{> "nav"}}
but I only get this
view/partials/nav
According to documentation arguments of .registerPartial(arg1, arg2) are:
Partial name
Partial content
Handlebars does not have built in functionality to serve static files from relative paths.
So without using external framework like for example the one hapijs uses to render views, what you can do is:
Handlebars.registerPartial('nav',
('<nav>' +
// your <nav> html
// ...
// ...
</nav>')
);
Related
I have an asp.net app with a site.js which is getting lengthy. What is the proper way to architect the file structure so that /home routes will load a home.js file and /product routes will load a routes.js file?
Ideally I would like to keep all the js files in the wwwroot folder and not next to the views or within them so I can minify them with the compiler
you can create an extension method for Html helper and call that on _Layout.cshtml as #Html.RenderControllerJs(Url); so that it gets called every time and inject the respective js.
public static class HtmlHelperExtentions
{
public static IHtmlContent RenderControllerJs(this HtmlHelper html, UrlHelper urlHelper)
{
var env = html.ViewContext.HttpContext.RequestServices.GetService<IHostEnvironment>();
var controllerName = html.ViewContext.RouteData.Values["Controller"].ToString().ToString();
var jsFileRelativePath = Path.Combine("<folder_path_for_all_controller_js>", $"{controllerName}.js");
var controllerJsFilePath = Path.Combine(env.ContentRootPath, jsFileRelativePath);
if (File.Exists(controllerJsFilePath))
{
return html.Raw(
$"<script type=\"text/javascript\" src=\"{urlHelper.Content(Path.Combine("~", jsFileRelativePath))}\"></script>");
}
return new HtmlString("");
}
}
You can also write custom logic specific to any controller. You have full control now.
Basically, I have a html file called panel containing a simple DIV that I would like to insert into another main HTML file.
Instead of using web components, I'd like to implement a simple solution as described in this answer.
So, here is what I am doing for testing (just logging the panel to console):
panel.html
<div id="panel">
<h1>It works...</h1>
</div>
get-template.ts
export async function getTemplate(filepath: string, selectors: string) {
let response = await fetch(filepath);
let txt = await response.text();
let html = new DOMParser().parseFromString(txt, 'text/html');
return html.querySelector(selectors);
}
main.ts
import { getTemplate } from './get-template'
getTemplate('/path/to/panel.html','#panel').then((panel) => {console.log(panel);})
The console logs "null".
If this info could make any difference, I am using parcel-bundler to build the application.
The actual problem was determined by #CBroe and was about the fact that when parcel builds my application, the file path of my panel.html resource changes to be relative to the built dist folder.
Just to clarify:
before building the path is relative to the main.ts file
after building the path is relative to the dist folder
So the solution is to think about the final URL the panel.html will have, and refer to it in advance before building with parcel.
Something like this would work in my case:
main.ts (new)
import { getTemplate } from './get-template'
getTemplate('./panel.html','#panel').then((panel) => {console.log(panel);})
Then of course, the other step will be to copy the actual panel.hml file into the dist directory, otherwise the URL will point to a non existing file.
I see there was a github issue about automatically copy static (or assets) files in the parcel repository, and one of the solution provided is to use the plugin parcel-plugin-static-files-copy.
I'm new to ASP.NET MVC. After reading many different examples I still can't get this done.
I have some JS scripts bundled and one out of the bundle (because I'm using a different main script per page)
(_Layout.cshtml)
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/datatables")
#RenderSection("scripts", required: false)
And in my view
(index.cshtml)
#section Scripts
{
<script src="#Url.Content("~/Scripts/index.js")"></script>
}
In javascript code I am trying to call a specific URL of my application
(index.js)
$('#table').DataTable({
ajax: '#Url.Action("List", "Documents")'
});
Of course in my application a controller is definend with the name DocumentsController and with a List method, returning the correct JSON.
Still it seems no-one is ever replacing my url
If I include my index.js in the bundle, nothing changes.
Where is the mistake?
Who and when is replacing that URL?
Thank you
You can't use Razor code inside a *.js file because they're served directly as static files and aren't processed by ASP.NET (nor *.ts files because they're transpiled to *.js at build-time).
What you can do instead is to render Razor-generated JavaScript in your View/Page and have your TypeScript or JavaScript expect that data to be available.
Like so:
Index.cshtml
<script type="text/javascript">
var scriptUrls = {
listDocuments: '#Url.Action("List", "Documents")';
};
</script>
Index.ts (if using TypeScript)
interface PageUrls {
readonly listDocuments: string;
};
declare var scriptUrls: PageUrls;
//
$('#table').DataTable({
ajax: scriptUrls.listDocuments
});
Index.js
$('#table').DataTable({
ajax: scriptUrls.listDocuments
});
Is there a way to compile directory of templates and store in array object using Webpack?
Explanation: I am now using list of handlebars templates. I precompile the list of templates using handlebars compiler in gulp.
gulp.src('client/src/templates/**/*.hbs')
.pipe(gulp_handlebars({
handlebars: handlebars,
compilerOptions:{
knownHelpers: helpers,
knownHelpersOnly:true}
}))
.pipe(wrap('Handlebars.template(<%= contents %>)'))
.pipe(declare({
namespace: 'appname.templates',
noRedeclare: true,
processName: function(filePath) {
return declare.processNameByPath(filePath.replace('client/src/templates/', ''));
}
}));
I would then access templates through appname.templates array. It was working fine.
Now, I am moving to Webpack. If I use the handlebars-loader ,
it allows me to require every template by name like
var template = require("./file.handlebars");
Is there a way to get all templates in one directory as an array like
var templates = require("./*.handlebars");
I usually would go to the folder you have your templates and have an templates/index.js file such as:
export templateA from './templateA.handlebars'
export templateB from './templateB.handlebars'
export templateC from './templateC.handlebars'
...
Then you can do:
import * as templates from './templates'
And templates is an object that holds all your templates. You can also do templates.templateA to access them by name.
I am learning backbone js, trying to make a small project.
In the of te page, I load require.js and text.js from the cloudflare CDN
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.8/require.min.js">//</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/require-text/2.0.10/text.js">//</script>
I have made a backbone view called "Boxes":
var Boxes = Backbone.View.extend({
// Choose an element.
el : '.content',
render : function () {
// Captur "this" -> the backbone view itself.
var that = this;
$(this.el).html('how do I load a html template here?');
}
});
Problems:
When I add the text.js plugin to the page, I get the following error:
Mismatched anonymous define() module: function (module) { 'use strict'; ......
So I can't have the require.js and the text.js both loaded, it gives me the above error even on a blank page without any other scripts on it.
After I make the require js work with text js, how do I load an html template for that view?
Right now I know how to do it when I write my templates inline, in the index.html page.
I do it like this:
var Boxes = Backbone.View.extend({
el : '.content',
render : function () {
var that = this; // This backbone view
var template = _.template($('#user-list-template').html(), {});
that.$el.html(template);
}
});
Thank you!
In your HTML file, you only need to load requrejs like as shown in this index.html
<script type="text/javascript" data-main="js/main" src="js/libs/require-2.1.2.min.js"></script>
In above, "data-main" tells requirejs where to load its bootstrap file and in this case, it is under "js/main.js"
You can find the file in here.
In the main.js file, you will need to specify
require.config({ ... });
to configure requirejs.
After that you can use "define()/require()" to load the templates like...
define(['text!../../templates/app/content.about.html'],...);
See here for a complete example.
When you use require.js, you only use one script tag in your page. Everything else is loaded by Require.js.
To use a plugin, you'll configure it in a require.config
require.config({
paths: {
text: "path/to/text"
}
});
Then in your modules, you simply call it:
define([
"text!path/to/tpl"
], function( tplString ) {
});
Note though, that if you're managing templates, the best would be to load the template pre-compiled. Text plugin only return a string, this is not very good for optimisation and force you to repeat the template compilation logic. You should use a template loader plugin, for underscore/lodash micro-template, I recommend you this one: https://github.com/tbranyen/lodash-template-loader
If you want an example of an app using Require.js and Backbone, you should really check Backbone-Boilerplate: https://github.com/backbone-boilerplate/backbone-boilerplate
Backbone-Boilerplate is good way to setup your project fast using the best practices around Backbone development. Plus it use AMD extensively, so you'll have a working setting if it is your first time around.