universal: Rendering Document Error: TypeError: undefined is not a function or str.replace is not a function
Note: for support questions, please use one of these channels: https://github.com/angular/universal/blob/master/CONTRIBUTING.md#question. This repository’s issues are reserved for feature requests and bug reports.
- I’m submitting a …
- bug report
- feature request
- support request => Please do not submit support request here, see note at the top of this template.
- What modules are related to this pull-request
- express-engine
- grunt-prerender
- gulp-prerender
- hapi-engine
- universal-preview
- universal
- webpack-prerender
- Do you want to request a feature or report a bug?
Report a bug
- What is the current behavior?
Note: This is purely guessing, as the error message isn’t descriptive enough for us to solve it.
An error is raised in the browser sometime: Rendering Document Error: TypeError: undefined is not a function
or Rendering Document Error: TypeError: str.replace is not a function
.
This (according to code), is probably angular universal trying to serialize an attribute with a falsy value, or not a string.
- If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem by creating a github repo.
Clone universal-starter
, replace home.template.html
by:
<div class="home" [hidden]="foo">
<form #loginForm="ngForm">
<input type="text" placeholder="username" required><br>
<button type="submit" [disabled]="!loginForm.form.valid">Login</button>
</form>
</div>
- What is the expected behavior?
No error
- Please tell us about your environment:
- Angular version: 2.0.0-rc4
- Browser: all
- Language: all
- OS: all
- Platform: NodeJS
- Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
Complete stacktraces:
Rendering Document Error: TypeError: str.replace is not a function
at escapeString (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:27:10)
at Serializer._serializeAttributes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:124:55)
at Serializer._serializeElement (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:91:10)
at Serializer._serializeChildNodes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:72:22)
at Serializer._serializeElement (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:114:14)
at Serializer._serializeChildNodes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:72:22)
at Serializer._serializeElement (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:114:14)
at Serializer._serializeChildNodes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:72:22)
at Serializer._serializeElement (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:114:14)
at Serializer._serializeChildNodes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:72:22)
Rendering Document Error: TypeError: undefined is not a function
at escapeString (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:27:10)
at Serializer._serializeAttributes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:124:55)
at Serializer._serializeElement (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:91:10)
at Serializer._serializeChildNodes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:72:22)
at Serializer._serializeElement (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:114:14)
at Serializer._serializeChildNodes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:72:22)
at Serializer._serializeElement (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:114:14)
at Serializer._serializeChildNodes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:72:22)
at Serializer._serializeElement (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:114:14)
at Serializer._serializeChildNodes (project\node_modules\angular2-universal\node_modules\parse5\lib\serialization\serializer.js:72:22)
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 5
- Comments: 23 (9 by maintainers)
The problem happens when the json document on the server is converted to a string and one of the elements has an attribute is not type string. Also check the MetaService (if you’re using it) to make sure the values are always string cc @vikerman @MarkPieszak
@felipedrumond @teemuandersen This should of been fixed in Master now but it might not of been published. When the latest and greatest comes out for rc5/6 then it will definitely be there!
it’s a bug in our propToAttr abstraction that was meant to convert these elements to attributes and our service that converts our fake-json-html-elements on the server to a string (our serializer).
When rendering on the server we’re converting an element to the string representation of that so for example.
<input id="myInput" value="hi'>
if I runwindow.myInput.view
I’ll get"hi"
because the document has an API that will convert attributes into properties after converting the markup into the correct js typeHTMLInputElement
if you change the value ofmyInput
to"yolo"
then view the element again you will notice that the attribute is stillvalue="hi"
yet the value is now"yolo"
. When converting these elements to string, when creating theindex.html
, we’re only looking at the attributes since there are way too many properties for each native element.For this case, the real problem is due to our serializer and propToAttr.
disabled
was returningdisabled="false"
wherefalse
is a boolean rather than a string. Our propToAttr was meant to remove these boolean attributes if they’re false and if they’re true only provide them without a value<input disabled="">
or<input disabled>