I am having trouble with serving a css file to the individual blog posts in the blog portion of my website.
So the way it works:
Go to /blog- you get the blog page and that works fine.
But when I am trying to get to, for example, /blog/post1 I am getting an error
http://localhost:4000/blog/static/css/style.css
I'd appreciate the help because I'm pretty new to express and routing files around and around. Cheers.
My file structure looks like this
blog
/node_modules
/src
/mock
/public
/css
style.css
/templates
/partials
_head.jade
_nav.jade
blog.jade
index.jade
layout.jade
post.jade
app.js
So the way it works:
Go to /blog- you get the blog page and that works fine.
But when I am trying to get to, for example, /blog/post1 I am getting an error
http://localhost:4000/blog/static/css/style.css
Here is what my respective files look like, maybe I'm missing something:
app.js
"use strict";
var express = require("express"),
posts = require("./mock/posts.json");
var postsLists = Object.keys(posts).map(function(value){
return posts[value]
});
var app = express();
app.use("/static", express.static(__dirname + "/public"))
app.set("view engine", "jade");
app.set("views", __dirname + "/templates");
app.get("/", function(req, res){
res.render("index");
});
app.get("/blog/:title?", function(req, res){
var title = req.params.title;
if (title === undefined) {
res.status(503);
res.render("blog", {posts: postsLists});
} else {
var post = posts[title] || {};
res.render("post", {post: post} );
}
});
app.get("/about", function(req, res){
res.send("<h1>About Page</h1>");
})
app.get("/projects", function(req, res){
res.send("<h1>Projects Page</h1>")
})
app.listen(4000, function(){
console.log("Frontend server is running on port 4000.")
});
_head.jade
head
meta(charset="UTF-8")
link(rel="stylesheet", href="static/css/style.css")
layout.jade
doctype html
html(lang="en")
include ./partials/_head.jade
body
block content
blog.jade
extends ./layout
block content
section(id="postHolder")
for post in posts
div.post
h2 #{post.title}
p #{post.body}
a(href="/blog/" + post.title)
button Read More
post.jade
extends ./layout.jade
block content
section
div.post
h2 #{post.title}
p #{post.body}
p This is the actual post page itself.
I guess doing this will get you there -
head
meta(charset="UTF-8")
link(rel="stylesheet", href="/css/style.css")
Okay so I want to draw your attention to my _head.jade file:
head
meta(charset="UTF-8")
link(rel="stylesheet", href="/static/css/style.css")
I needed to make a reference to the absolute path and add the "/" in front of "static"
It used to be static/css/style.css and now it's
/static/css/style.css I'm pretty new to this and I don't know if I explained the reference to the absolute path correctly.
Related
I'm trying to create a nested route inside my nextjs project, but i'm receiving a 404 page not found when trying to request the page.
I have a route named /dashboard/repository/blender where blender is a dynamic name that the user can input and that works fine.
But the next step is then to create a subpage for that dynamic route which is named tags, and that's where I receive the 404. (/dashboard/repository/blender/tags)
Here's a screenshot of what i've tried to achieve the tags nested routing
Secondly I have also tried doing the following
What can I do to achieve this ?
Try that structure please
dashboard (folder)
-repository (folder)
--[blender] (folder)
----tags.tsx (file)
example urls
/dashboard/repository/blender/tags
/dashboard/repository/surrender/tags
...
In your component, you can get it like below
tags.tsx
import { useRouter } from 'next/router'
const C = () => {
const router = useRouter()
const { blender } = router.query;
console.log(blender)
}
Solved it with
- /dashboard/repository/[repository]/index.js
- /dashboard/repository/[repository]/tags.js
Problem
I am trying to write a Single Page Application (SPA) where initially the app shows module "A". When the user clicks an element in "A", module "B" is displayed and is passed an ID from A. (For example A displays a list of Employee IDs, clicking on one employee means B will display details of that employee)
Initially my URL is :
http://localhost:8000/
Clicking on an item in A with an id of 123, the URL changes to following which is correct:
http://localhost:8000/A/123
However, I get the following error
GET http://localhost:8000/b/js/viewModels/B.js net::ERR_ABORTED 404 (Not Found)
ojModule failed to load viewModels/B
ojlogger.js:257 Error: Script error for "viewModels/B"
I do not know why it has changed the path and added an extra "/b/" to get the B.js/B.html file. Of course it can not find this file as there is no such folder "b" in my project structure.
Oracle Jet Cookbook Sample
https://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=router&demo=stateParams
I am using the sample in the OracleJet Cookbook for a Router with State Parameters. If you open this example in full screen you see that the URL for the first screen (A) is
https://www.oracle.com/webfolder/technetwork/jet/content/router-stateParams/demo.html
Clicking on a person in the list changes the URL to the following, which is the same as mine.
https://www.oracle.com/webfolder/technetwork/jet/content/router-stateParams/demo.html/detail/7566
This cookbook sample does not error like mine.
My Code
project structure
src
|- index.html
|- js
|- main.js
|- viewModels
|- A.js
|- B.js
|- views
|- A.html
|- B.html
index.html
....
<body>
<div id="routing-container">
<div data-bind="ojModule:router.moduleConfig"></div>
</div>
</body>
....
main.js
requirejs.config(
{
baseUrl: 'js',
....
}
require(['ojs/ojbootstrap', 'ojs/ojrouter', 'knockout', 'ojs/ojmodule-element-utils', 'ojs/ojknockout', 'ojs/ojmodule'],
function (Bootstrap, Router, ko) {
// Retrieve the router static instance and configure the states
var router = Router.rootInstance;
router.configure({
'a': {label: 'a', value: 'A', isDefault: true},
'b/{id}': {label: 'b', value: 'B' }
});
var viewModel = {
router: router
};
Bootstrap.whenDocumentReady().then(
function(){
ko.applyBindings(viewModel, document.getElementById('routing-container'));
Router.sync();
}
);
});
A.html
....
<div on-click="[[onClicked]]" >
....
</div>
...
A.js
define(['ojs/ojcore', 'ojs/ojrouter', 'knockout', '],
function (oj, Router, ko) {
function AViewModel(params) {
....
router = Router.rootInstance;
....
this.onClicked= function(event) {
router.go('b/'+ 123);
}
....
};
}
return AViewModel;
}
Attempts
I have tried adding one of the following in "main.js" and it doesn't make a difference.
Router.defaults['baseUrl'] = '';
Router.defaults['baseUrl'] = 'js';
Router.defaults['baseUrl'] = '/js';
Router.defaults['baseUrl'] = '/js/';
Updated answer after gleeming more information
I have finally resolved this with some advice from a colleague.
Make sure the "baseUrl" specified in your requireJS is absolute when you are using the urlPathAdapter router.
main.js
requirejs.config(
{
baseUrl: '/js',
RequireJS's baseUrl is used as the starting location for RequireJS to download its relative content. Most of the time its set to "js" but that will not work nicely with the UrlPathAdapter router. This is because the router will change the URL which RequireJS tries to add its path to when its not absolute. The result is that the path requireJS is trying to use to get its content is invalid.
For example:
you accessed your app with the URL "protocol://server:port/my/app"
RequireJS will try and access content by appending "js", for example "protocol://server:port/my/app/js/viewModel/..." which works when you are at the root of your application
you use the router to navigate to a different url, the url is now "protocol://server:port/my/app/newPath"
now RequireJS will try and use the URL "protocol://server:port/my/app/newPath/js/viewModel" which is wrong
When the RequireJS baseURL is absolute, it will always be added to the apps URL, for example "protocol://server:port/my/app/js/viewModel" where the content will be found
NOTE: I also ensured the baseUrl in "path-mapping" was absolute as well
path_mapping.json
{
"baseUrl": "/js",
Another solution was to change my router adapter from the default urlPathAdapter to urlParamAdapter.
Router.defaults.urlAdapter = new Router.urlParamAdapter();
var router = Router.rootInstance;
I have a SPA, I want to use routing for ng-view.
I have the code included in a page at domain.com/folder/dashboard.aspx
This is just a piece of that existing page, I can't move it elsewhere.
When I use route /list it alters my url to domain.com/folder/list/ which works, but breaks the ability to refresh the page (and gives a 404 since dashboard.aspx is not a default page, nor can it be)
How can I keep the url as domain.com/folder/dashboard.aspx/list?
I did try to setup my routes as dashboard.aspx/list and other various similar adjustments, but didn't have any luck.
Just like what #Claies said, it should be handled in your server config, just gonna drop my route config here in case you haven't tried this yet
var routeWithoutResolving = function (template: string, title?: string, style?: string) {
var name;
var slashIdx = template.indexOf('/');
if (slashIdx !== -1) {
name = template.substring(0, slashIdx);
template = template.substring(slashIdx + 1);
} else {
name = template;
}
var templateUrl = '/folder/' + template + '.aspx/';
return {
templateUrl: templateUrl,
title: title,
style: style,
area: _.capitalize(name),
page: template,
reloadOnSearch: false
}
}
Usage
.when('/domain.com/folder/dashboard.aspx/list', routeWithoutResolving ('folder/dashboard.aspx'))
I figured it out.
You can't use HTML5 mode, you have to be using Hashbang.
I set my routes as normal, /list and /list/item
For my links, I just used full urls, with the Dashboard.aspx#!/list/item and /list
I also removed the base tag from the html page
I want to serve a static HTML file from MeteorJS's public folder (as is possible with Rails and Express). The reason I'm doing this is because I have one template for the dynamic "admin" part of my webapp and another for the sales-y "frontend" part of the app.
I don't want this file to be wrapped in a Meteor template as suggested in this answer as it will automatically bring in the minified CSS, etc... that the dynamic pages use.
Is there a way I can setup the public folder (and all its subfolders) so that it serves index.html? This way http://app.com/ will load public/index.html?
You could use the private folder instead and then use Assets.getText to load the contents of the file, then serve it with a server-side router from iron-router.
So off the top of my head the code would look something like this:
if (Meteor.isServer) {
Router.map(function() {
this.route('serverRoute', {
path: '/',
where: 'server',
action: function() {
var contents = Assets.getText('index.html');
this.response.end(contents);
}
});
});
}
this is what I put in bootstrap.js
Router.route('/', {
where: 'server'
}).get(function() {
var contents;
contents = Assets.getText('index.html');
return this.response.end(contents);
});
I was hoping anyone could give some input on this,
I'm creating a meteor app in which I would like to use bootstrap to creating the admin environment, but have the visitor facing side using custom css. When I add the bootstrap package to my app using meteor it's available on every page, is there a way to restrict the loading of bootstrap to routes that are in '/admin' ?
When you add bootstrap package it's not possible. You can, however, add bootstrap csses to public directory and then load them in a header subtemplate that will only be rendered when you're in the dashboard.
EDIT
But then how would you go about creating seperate head templates?
Easy:
<head>
...
{{> adminHeader}}
...
</head>
<template name="adminHeader">
{{#if adminPage}}
... // Put links to bootstrap here
{{/if}}
</template>
Template.adminHeader.adminPage = function() {
return Session.get('adminPage');
}
Meteor.router.add({
'/admin': function() {
Session.set('adminPage', true);
...
}
});
DISCLAIMER: I am unsure of a 'meteor way' to do this, so here is how I would do it with plain JS.
jQuery
$("link[href='bootstrap.css']").remove();
JS - Credit to javascriptkit
function removejscssfile(filename, filetype){
var targetelement=(filetype=="js")? "script" : (filetype=="css")? "link" : "none" //determine element type to create nodelist from
var targetattr=(filetype=="js")? "src" : (filetype=="css")? "href" : "none" //determine corresponding attribute to test for
var allsuspects=document.getElementsByTagName(targetelement)
for (var i=allsuspects.length; i>=0; i--){ //search backwards within nodelist for matching elements to remove
if (allsuspects[i] && allsuspects[i].getAttribute(targetattr)!=null && allsuspects[i].getAttribute(targetattr).indexOf(filename)!=-1)
allsuspects[i].parentNode.removeChild(allsuspects[i]) //remove element by calling parentNode.removeChild()
}
}
removejscssfile("bootstrap.css", "css")
However, doing that would complete remove it from the page. I am not sure whether meteor would then try to readd it when a user goes to another page. If that does not automatically get readded, then you have an issue of bootstrap not being included when someone goes from the admin section to the main site, which would break the look of the site.
The way I would get around that would be to disable and enable the stylesheets:
Meteor.autorun(function(){
if(Session.get('nobootstrap')){
$("link[href='bootstrap.css']").disabled = true;
}else{
$("link[href='bootstrap.css']").disabled = false;
}
});
There my be other bootstrap resources which may need to be removed, take a look at what your page is loading.
To use jQuery in the same way but for the javascript files, remember to change link to script and href to src
From my tests, Meteor does not automatically re-add the files once they have been removed so you would need to find some way of re-adding them dynamically if you want the same user to be able to go back and forth between the main site and the admin site. Or simply if the http referrer to the main site is from the admin, force reload the page and then the bootstrap resources will load and everything will look pretty.
P.s. make sure you get the href correct for the jQuery version
If somebody is interested in including any js/css files, I've written a helper for it:
if (Meteor.isClient) {
// dynamic js / css include helper from public folder
Handlebars.registerHelper("INCLUDE_FILES", function(files) {
if (files != undefined) {
var array = files.split(',');
array.forEach(function(entity){
var regex = /(?:\.([^.]+))?$/;
var extension = regex.exec(entity)[1];
if(extension == "js"){
$('head').append('<script src="' + entity + '" data-dynamicJsCss type="text/javascript" ></script>');
} else if (extension == "css"){
$('head').append('<link href="' + entity + '" data-dynamicJsCss type="text/css" rel="stylesheet" />');
};
});
}
});
Router.onStop(function(){
$("[data-dynamicJsCss]").remove();
});
}
Then simply use:
{{INCLUDE_FILES '/css/html5reset.css, /js/test.js'}}
in any of your loaded templates :)