I need to create a component that displays the content of another webpage.
So for instance if I have the site of stackoverflow, I would like to create a component that does a http request and displays the content through my app. By the way, the external website is just django-rest-swagger and to access it, I need to include a header everytime I access it. So, when I make the request for the external site content I need to inlclude the header x-forwarded-host.
<div>
<html> CONTENT OF EXTERNAL WEBSITE </html>
</div>
thank you
#Component({
selector: ...
template: `<div [innerHTML]="fetchedHtml"></div>
})
export class ExternalHtml {
constructor(http:Http) {
var headers = new Headers();
headers.append('x-forwarded-host', 'foo');
http.get('someUrl', {headers: headers}).subscribe(response => {
this.fetchedHtml = response.json();
}
}
See also
In RC.1 some styles can't be added using binding syntax
Alternatively you can also use an iframe to display the fetched HTML.
You can display it as follows:
<div [innerHTML]="contentOfTheExternalWebsite">
</div>
Related
Im new to nextjs, and Im checking if it will be good for the app that will have pretty complex and messy internal navigation. Just checked their documentation and I see that they recommend usage
of Link component like this <Link href="/your_path">Path</Link>. A bit scary is that I have to provide 'your_path' as a string so every time i change page file name I have to manually update code that redirects to this page. Is there any solution that allows me to define routing on my own so I can write something like (pseudocode)
routes = [
...
{
page : 'page_name',
path : 'path_to_page'
}
...
]
So instead of using string I can do <Link href="{route.path}">Path</Link> or Im condemned to use this file-system based router with all consequences?
The simple answer is yes!
When you want to change a user route in NextJs you have 2 options,
The first is with the <Link> Element that you can specify a href to where it directs.
And you also have a useRouter hook for more complex routing for example if the user does an action that requires moving him into a different route you can do it internally in your handlers.
For more information about useRouter hook.
What I usually do is storing my routes in an object
const ROUTES = {
HOME: "/",
ABOUT: "/about"
}
and wherever you call routes you just use the object so F.E
With Link tag
<Link href={ROUTES.ABOUT}>ABOUT PAGE</Link>`
with useRouter hook
// Inside a React Component
const router = useRouter();
const handleNavigateToAbout = () => {
router.push(ROUTES.ABOUT);
}
return (
// SOME JSX
<button onClick={handleNavigateToAbout}> Go to about page! </button>
)
Assume we have a web page with the HTML lang attribute set dynamically based on the Accept-language header of the request. The body of the page is also language-specific. What I came up with:
require('svelte/register')
// Render the body
const Body = require('./Body.svelte').default
const body = Body.render({ language })
// Render the entire page
const Page = require('./Page.svelte').default
const page = Page.render(Object.assign(body, { language })
// Send page.html to the client
Where Page.svelte is:
<script>
export let html
export let language
</script>
<!DOCTYPE html>
<html lang="{ language }">
<body>
{ #html html }
</body>
</html>
Everything works fine. But now I'd like to have the page interact. I use the Body.svelte in the App and set hydrate option:
const app = new App({
target: document.body,
hydrate: true
})
Without this option set the content is rendered twice. With the option set we have an error in the browser:
Uncaught Error: options.hydrate only works if the component was compiled with the `hydratable: true` option
We can pass options to the compiler, according to the documentation:
require('svelte/register')({ hydratable: true })
It says:
hydratable: true adds a marker to each element in the <head> so that the component knows which elements it's responsible for removing during hydration
But I observe no markers. It has no effect on client-side rendering, and the error remains.
Am I missing something?
I've had a few errors trying to render single blog posts.
I tried using the page template with /post/{post_name} and I was getting this error:
warn Non-deterministic routing danger: Attempting to create page: "/blog/", but
page "/blog" already exists
This could lead to non-deterministic routing behavior
I tried again with /blog/{post_name}.
I now have both routes, which I'm not sure how to clean up; but more importantly, on those pages, nothing renders, even though there should be an h1 with it's innerhtml set to the node.title and likewise a div for the content.
I've uploaded my config and components to https://github.com/zackrosegithub/gatsby so you can have a look.
Not sure how to fix
I just want to see my content rendered on the screen.
Developer tools don't seem to help when there's no content rendered as I can't find anything to inspect to try to access it another way.
Thank you for your help
Your approach is partially correct. You are using a promise-based approach but when using then() you are already settling and partially resolving it so you don't need to use the callback of resolve(), which may be causing a duplication of the promise function so try removing it.
Additionally, you may want to use a more friendly approach using async/await functions. Something like:
exports.createPages = async ({ graphql, actions, reporter }) => {
const yourQuery= await graphql(
`
{
allWordpressPost {
edges{
node{
id
title
slug
excerpt
content
}
}
}
}
`
if (yourQuery.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`);
return;
}
const postTemplate = path.resolve("./src/templates/post.js")
_.each(yourQuery.data.allWordpressPost.edges, edge => {
createPage({
path: `/post/${edge.node.slug}/`,
component: slash(postTemplate),
context: edge.node,
})
})
})
// and so on for the rest of the queries
};
In addition, place a console.log(pageContext) in your postTemplate to get what's reaching that point and name the template as:
const Post = ({pageContext}) => {
console.log("your pageContext is", pageContext);
return <div>
<h1>
{pageContext.title}
</h1>
</div>
}
export default Post;
I am using FlowRouter as a router for a Meteor/React application I am trying to create. I'm having a very hard time trying to get my react components to render in specific places. Does anyone know how to do this?
So on my landing page, when I click a button, I want to route to a secondary page. I have three different components that I want to render in certain parts of the page. I've been using ReactLayout.render(), but I can't seem to make sure components get rendered in certain areas. I thought document.getElementById would work
ReactLayout.render(LandingPage, document.getElementById("landing-page")
but it hasn't been.
The second parameter of ReactLayout.render expects an object. If you want to render several components into your LandingPage element, it might look something like this:
LandingPage = React.createClass({
render() {
return (
<div className="app-root">
<AppHeader />
<div className="container">
{this.props.testOne}
</div>
<div className="app-root">
{this.props.testTwo}
</div>
</div>
);
}
});
Then render using:
FlowRouter.route( '/testRedirect', {
name: 'test',
action() {
ReactLayout.render( Default, { testOne: <TestOneComponent />, testTwo: <TestTwoComponent /> } );
}
});
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 :)