Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support rendering just a single component rather than a complete HTML document #347

Closed
SteveSandersonMS opened this issue Apr 5, 2016 · 15 comments

Comments

@SteveSandersonMS
Copy link

As discussed, please add support for rendering just a single component element to an HTML string, instead of requiring the template to be an entire HTML document.

For example, instead of this:

ngUniversal.bootloader({
    ...,
    template: '<!DOCTYPE html>\n<html><head></head><body><app></app></body></html>'
})

... it should be possible to do this:

ngUniversal.bootloader({
    ...,
    template: '<app></app>'
})

Currently, Angular Universal automatically wraps the output in <html> etc even if it wasn't requested in the template. This feature is particuarly relevent when including Angular 2 server-side rendered content in an existing server-rendered page, e.g., on ASP.NET.

@MarkPieszak
Copy link
Member

I could try and take this one if it's not too difficult you think @gdi2290 ?

It sounds like we just need to be testing for the existence of <!doctype> or <html> etc and not applying it if need be?

@jeffwhelpley
Copy link
Contributor

@gdi2290 We should have this as a high priority. What is involved in this change?

@MarkPieszak
Copy link
Member

@SteveSandersonMS Hey Steve, the initial html page that you are pointing to for Universal, has no <html></html> <body></body> tags, etc correct?

I have a fix for this in the works, trying to look into it more to make sure I cover everything.

I'm also wondering how we can get <universal-styles /> to work (and inject CSS) if we have no supplied tags in the <head>

@SteveSandersonMS
Copy link
Author

The ASP.NET templates don't point to any initial HTML page in the sense that I think you mean. We're not using the angular2-universal view engine or any equivalent. We are using angular-universal just to render-as-string individual Angular 2 components that get injected into a page being generated by ASP.NET.

You can find an example of the server-side boot code we're using here: https://github.com/aspnet/NodeServices/blob/master/templates/Angular2Spa/ClientApp/boot-server.ts

You'll see below the TODO comment there about this issue what markup we currently have to pass to angular2-universal as a workaround. We just need angular2-universal not to assume it's working on an entire HTML document, and to be happy working on an arbitrary document fragment.

I'm also wondering how we can get to work (and inject CSS) if we have no supplied tags in the

Could the serializeApplication method return both html and css strings (currently it just returns an html string)? We can take care of injecting them into the right parts of the page.

@PatrickJS
Copy link
Member

I'm working on this today after Jsonp support

@MarkPieszak
Copy link
Member

@gdi2290 I'm not sure if you saw my message on the Slack a while back, but to me, it looked like using parseFragment helped not create the entire <html> tree. Not sure if that would help you at all!

@jeffwhelpley
Copy link
Contributor

@gdi2290 what is the status here? we currently don't have the ability to do the html component, right?

@MarkPieszak
Copy link
Member

Originally it worked when I just looked to see if there was doc type, an html tag etc (then proceed like normal), otherwise do parseFragment on the or whatever was passed in and it did seem to work. @jeffwhelpley think the codes still there, just commented out.

@jeffwhelpley
Copy link
Contributor

OK, so in that case, this issue is dependent on #533 which is a top priority right now. Let's focus on that and then we can come back to this.

@MarkPieszak
Copy link
Member

MarkPieszak commented Oct 4, 2016

Sounds good to me, yea there's definitely a lot of high priority stuff right now.

@SteveSandersonMS
Copy link
Author

It looks to me like this is now fixed. At least, there's no longer any error when prerendering just a template containing <app></app>, rather than an entire <html>...</html> doc.

Could you confirm whether this is now officially supported? It's not going to break anything subtle in angular-universal if people start just passing <app></app> as the template?

@MarkPieszak
Copy link
Member

MarkPieszak commented Oct 31, 2016

Hey @SteveSandersonMS we updated to parse5 2.* a while back, which now returns a ASTNode.Document, so that might be why it isn't erroring out anymore. The problem is now the page will have 2 <html><head><body> tags since it's going to return those back for you. When you view source you'll be able to see them inside your original <app> tag you passed.

I just tested it out, and it does work, but we still want to be using parseFragment in this situation.

Also, I tried adding in my original logic on our side, and it worked in running parseFragment (since in your case <html> </html> isn't found in the document string.
@gdi2290 Is this adequate enough of a test for this situation?

I'll create a PR #614 about it so we can get this one ironed out.

  // Build entire doc <!doctype><html> etc
  if (documentHtml.indexOf('<html>') > -1 && documentHtml.indexOf('</html>') > -1) {
    doc = parse5.parse(documentHtml, { treeAdapter : parse5.treeAdapters.htmlparser2 });
  } else {
    // ASP.NET case : parse only the fragment - don't build entire <html> doc
    doc = parseFragment(documentHtml);
  }

@PatrickJS
Copy link
Member

PatrickJS commented Oct 31, 2016

this will still be an issue without replacing all of the platform services being created in core such as Meta Service (in PR angular/angular#12322), Title Service (already in), ignore Base element, ResourceLoader, and replace Style Host to not use an element.

Angular core wants to be agnostic to the platform which means everything should live within the app element tag. The problem is that is not that case as there are platform services that are needed to change values outside of that element. Platform services are slowly being built out now that final is released. platform-node needs to provide a way to manage these platform services in the case where there is no full document and then provide a way to grab these global values and return them.

@PatrickJS
Copy link
Member

might be supported in ng4
angular/angular#13822

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants