yarn add @ng-dnd/core react-dnd-html5-backend
You might consider @ng-dnd/multi-backend
instead of the HTML5
backend, because it allows adding touch support as well.
Then import DndModule
and provide the backend:
import { DndModule } from '@ng-dnd/core';
import { HTML5Backend } from 'react-dnd-html5-backend';
@NgModule({
imports: [
// Don't forget the forRoot()
DndModule.forRoot({ backend: HTML5Backend }),
],
})
export class AppModule {}
If you need it again on a child module, like a lazy-loaded module, you only need
to import DndModule
there. That way the backend and global drag state is only
initialized once. But you may use forRoot
to inject a new instance or to
include drag and drop on only some child modules.
These pieces make up the library:
react-dnd
defined one more thing, inspired by HTML5, to make using this sane:
each item has a type, and drag sources and drop targets will
respectively emit and accept only items with matching types.
That's it. This library offers all those concepts in an Angular-friendly way,
that is also largely compatible with a lot of react-dnd
code and examples.
Have a look at the Examples, and browse their source code in the examples app on GitHub.
Read and follow the Tutorial
Read the 3-part guide in the sidebar. Any specifics are available by browsing the interfaces and classes.
Mobile devices have not implemented HTML5 drag and drop. You will need:
A good way to solve both problems at once is using
@ng-dnd/multi-backend
. It is based on the original
dnd-multi-backend, which was designed to seamlessly switch
between an HTML5 and a touch backend when it noticed different
kinds of interaction. The @ng-dnd
version includes a preview component.
Note also that you will need to use an exported function
to provide the backend, to retain AOT compatibility, if it requires assembly.
MultiBackend
, for example, can be used like so:
export function createBackend() {
return MultiBackend(HTML5ToTouch);
}
@NgModule({
imports: [
DndModule.forRoot({ backendFactory: createBackend })
]
}
// ...
TypeError: backend is null
, only when AOT is enabledAlso rears its head as No such property 'default' of undefined
.
Troubleshooting steps
Check you are importing the backend and renaming any default exports.
Example :import { HTML5Backend } from 'react-dnd-html5-backend';
import { SomeImaginaryBackendWithNamedExports } from 'some-imaginary-backend';
Generally, make sure you are importing the backend correctly. If it does not provide Typescript definitions, you might have to read the documentation or browse the source code.
Make sure in your root Angular module (usually app.module.ts
) you import
DndModule.forRoot({ backend: MyBackend })
instead of plain DndModule
.
Error encountered resolving symbol values statically. Calling function 'default'
with AOT enabled.Make sure you are following the special instructions for assembly-required backends
like MultiBackend
or any backend that allows SomeBackend({ optionsHere: true })
,
like TouchBackend
. See above.
this.method()
!Make sure you use the arrow function syntax (() =>
) in your specs so this
will refer to your component. Example:
paperCount = 3;
limitedSupplyOfPaper = this.dnd.dragSource('PAPER', {
// use shorthand for one-liners that return a value
canDrag: () => this.paperCount > 0,
endDrag: monitor => {
if (monitor.didDrop()) {
this.paperCount--;
}
},
});
This demo shows comprehensively what this
refers to
in arrow functions vs regular ones. A sufficiently advanced editor shouldn't
show any completions at this.|
in a regular function, as it will resolve the
type of this
to be any
.