105 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # `Renderer` to `Renderer2` migration
 | ||
| 
 | ||
| ## Migration Overview
 | ||
| 
 | ||
| The `Renderer` class has been marked as deprecated since Angular version 4.
 | ||
| This section provides guidance on migrating from this deprecated API to the newer `Renderer2` API and what it means for your app.
 | ||
| 
 | ||
| ## Why should I migrate to Renderer2?
 | ||
| 
 | ||
| The deprecated `Renderer` class has been removed in version 9 of Angular, so it's necessary to migrate to a supported API.
 | ||
| Using `Renderer2` is the recommended strategy because it supports a similar set of functionality to `Renderer`.
 | ||
| The API surface is quite large (with 19 methods), but the schematic should simplify this process for your applications.
 | ||
| 
 | ||
| ## Is there action required on my end?
 | ||
| 
 | ||
| No.
 | ||
| The schematic should handle most cases with the exception of `Renderer.animate()` and `Renderer.setDebugInfo()`, which already aren't supported.
 | ||
| 
 | ||
| ## What are the `__ngRendererX` methods? Why are they necessary?
 | ||
| 
 | ||
| Some methods either don't have exact equivalents in `Renderer2`, or they correspond to more than one expression.
 | ||
| For 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`:
 | ||
| 
 | ||
| ```ts
 | ||
| const [namespace, name] = splitNamespace(namespaceAndName);
 | ||
| const el = renderer.createElement(name, namespace);
 | ||
| if (parentNode) {
 | ||
|   renderer.appendChild(parentNode, el);
 | ||
| }
 | ||
| return el;
 | ||
| ```
 | ||
| 
 | ||
| Migration has to guarantee that the return values of functions and types of variables stay the same.
 | ||
| To handle the majority of cases safely, the schematic declares helper functions at the bottom of the user's file.
 | ||
| These helpers encapsulate your own logic and keep the replacements inside your code down to a single function call.
 | ||
| Here's an example of how the `createElement()` migration looks:
 | ||
| 
 | ||
| 
 | ||
| **Before:**
 | ||
| 
 | ||
| ```ts
 | ||
| public createAndAppendElement() {
 | ||
|   const el = this.renderer.createElement('span');
 | ||
|   el.textContent = 'hello world';
 | ||
|   return el;
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| **After:**
 | ||
| 
 | ||
| <code-example>
 | ||
| 
 | ||
| public createAndAppendElement() {
 | ||
|   const el = __ngRendererCreateElement(this.renderer, this.element, 'span');
 | ||
|   el.textContent = 'hello world';
 | ||
|   return el;
 | ||
| }
 | ||
| // Generated code at the bottom of the file
 | ||
| __ngRendererCreateElement(renderer: any, parentNode: any, nameAndNamespace: any) {
 | ||
|   const [namespace, name] = __ngRendererSplitNamespace(namespaceAndName);
 | ||
|   const el = renderer.createElement(name, namespace);
 | ||
|   if (parentNode) {
 | ||
|     renderer.appendChild(parentNode, el);
 | ||
|   }
 | ||
|   return el;
 | ||
| }
 | ||
| __ngRendererSplitNamespace(nameAndNamespace: any) {
 | ||
|   // returns the split name and namespace
 | ||
| }
 | ||
| 
 | ||
| </code-example>
 | ||
| 
 | ||
| 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.
 | ||
| 
 | ||
| ### I’m a library author. Should I run this migration?
 | ||
| 
 | ||
| **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.**
 | ||
| 
 | ||
| 
 | ||
| ### Full list of method migrations
 | ||
| 
 | ||
| The following table shows all methods that the migration maps from `Renderer` to `Renderer2`.
 | ||
| 
 | ||
| |Renderer|Renderer2|
 | ||
| |---|---|
 | ||
| |`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()`)|
 |