{ "id": "guide/migration-renderer", "title": "Renderer to Renderer2 migration", "contents": "\n\n\n
\n mode_edit\n
\n\n\n
\n

Renderer to Renderer2 migrationlink

\n

Migration Overviewlink

\n

The Renderer class has been marked as deprecated since Angular version 4.\nThis section provides guidance on migrating from this deprecated API to the newer Renderer2 API and what it means for your app.

\n

Why should I migrate to Renderer2?link

\n

The deprecated Renderer class has been removed in version 9 of Angular, so it's necessary to migrate to a supported API.\nUsing Renderer2 is the recommended strategy because it supports a similar set of functionality to Renderer.\nThe API surface is quite large (with 19 methods), but the schematic should simplify this process for your applications.

\n

Is there action required on my end?link

\n

No.\nThe schematic should handle most cases with the exception of Renderer.animate() and Renderer.setDebugInfo(), which already aren't supported.

\n

What are the __ngRendererX methods? Why are they necessary?link

\n

Some methods either don't have exact equivalents in Renderer2, or they correspond to more than one expression.\nFor example, both renderers have a createElement() method, but they're not equal because a call such as renderer.createElement(parentNode, namespaceAndName) in the Renderer corresponds to the following block of code in Renderer2:

\n\nconst [namespace, name] = splitNamespace(namespaceAndName);\nconst el = renderer.createElement(name, namespace);\nif (parentNode) {\n renderer.appendChild(parentNode, el);\n}\nreturn el;\n\n

Migration has to guarantee that the return values of functions and types of variables stay the same.\nTo handle the majority of cases safely, the schematic declares helper functions at the bottom of the user's file.\nThese helpers encapsulate your own logic and keep the replacements inside your code down to a single function call.\nHere's an example of how the createElement() migration looks:

\n

Before:

\n\npublic createAndAppendElement() {\n const el = this.renderer.createElement('span');\n el.textContent = 'hello world';\n return el;\n}\n\n

After:

\n\n\npublic createAndAppendElement() {\n const el = __ngRendererCreateElement(this.renderer, this.element, 'span');\n el.textContent = 'hello world';\n return el;\n}\n// Generated code at the bottom of the file\n__ngRendererCreateElement(renderer: any, parentNode: any, nameAndNamespace: any) {\n const [namespace, name] = __ngRendererSplitNamespace(namespaceAndName);\n const el = renderer.createElement(name, namespace);\n if (parentNode) {\n renderer.appendChild(parentNode, el);\n }\n return el;\n}\n__ngRendererSplitNamespace(nameAndNamespace: any) {\n // returns the split name and namespace\n}\n\n\n

When implementing these helper functions, the schematic ensures that they're only declared once per file and that their names are unique enough that there's a small chance of colliding with pre-existing functions in your code. The schematic also keeps their parameter types as any so that it doesn't have to insert extra logic that ensures that their values have the correct type.

\n

I’m a library author. Should I run this migration?link

\n

Library authors should definitely use this migration to move away from the Renderer. Otherwise, the libraries won't work with applications built with version 9.

\n

Full list of method migrationslink

\n

The following table shows all methods that the migration maps from Renderer to Renderer2.

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
RendererRenderer2
listen(renderElement, name, callback)listen(renderElement, name, callback)
setElementProperty(renderElement, propertyName, propertyValue)setProperty(renderElement, propertyName, propertyValue)
setText(renderNode, text)setValue(renderNode, text)
listenGlobal(target, name, callback)listen(target, name, callback)
selectRootElement(selectorOrNode, debugInfo?)selectRootElement(selectorOrNode)
createElement(parentElement, name, debugInfo?)appendChild(parentElement, createElement(name))
setElementStyle(el, style, value?)value == null ? removeStyle(el, style) : setStyle(el, style, value)
setElementAttribute(el, name, value?)attributeValue == null ? removeAttribute(el, name) : setAttribute(el, name, value)
createText(parentElement, value, debugInfo?)appendChild(parentElement, createText(value))
createTemplateAnchor(parentElement)appendChild(parentElement, createComment(''))
setElementClass(renderElement, className, isAdd)isAdd ? addClass(renderElement, className) : removeClass(renderElement, className)
projectNodes(parentElement, nodes)for (let i = 0; i < nodes.length; i++) { appendChild(parentElement, nodes[i]); }
attachViewAfter(node, viewRootNodes)const parentElement = parentNode(node); const nextSibling = nextSibling(node); for (let i = 0; i < viewRootNodes.length; i++) { insertBefore(parentElement, viewRootNodes[i], nextSibling);}
detachView(viewRootNodes)for (let i = 0; i < viewRootNodes.length; i++) {const node = viewRootNodes[i]; const parentElement = parentNode(node); removeChild(parentElement, node);}
destroyView(hostElement, viewAllNodes)for (let i = 0; i < viewAllNodes.length; i++) { destroyNode(viewAllNodes[i]); }
setBindingDebugInfo()This function is a noop in Renderer2.
createViewRoot(hostElement)Should be replaced with a reference to hostElement
invokeElementMethod(renderElement, methodName, args?)(renderElement as any)[methodName].apply(renderElement, args);
animate(element, startingStyles, keyframes, duration, delay, easing, previousPlayers?)Throws an error (same behavior as Renderer.animate())
\n\n \n
\n\n\n" }