diff --git a/README.md b/README.md
index 331ccc93..1b547c5a 100644
--- a/README.md
+++ b/README.md
@@ -186,6 +186,11 @@ export class EventExample {
}
```
+## Special dragulaOptions for ng2-dragula
+
++ initAfterView: Allows for delayed initialization of the directive. Binds in Angulars AfterViewInit event.
++ childContainerSelector: Allows the ability to use a child element as the container for drag and drop when access to the element is not possible. Uses querySelector for finding the child element from directives container.
+
## Special Events for ng2-dragula
| Event Name | Listener Arguments | Event Description |
diff --git a/demo/src/app/app.component.ts b/demo/src/app/app.component.ts
index 6fd6eca0..40a2ab5c 100755
--- a/demo/src/app/app.component.ts
+++ b/demo/src/app/app.component.ts
@@ -21,6 +21,8 @@ import { Component, ViewEncapsulation } from '@angular/core';
+
+
`,
encapsulation: ViewEncapsulation.None
diff --git a/demo/src/app/examples.ts b/demo/src/app/examples.ts
index 6f813159..a5d8b5ae 100644
--- a/demo/src/app/examples.ts
+++ b/demo/src/app/examples.ts
@@ -194,6 +194,53 @@ export class NestedRepeatExampleComponent {
];
}
+@Component({
+ selector: 'table-example',
+ templateUrl: './templates/table-example.html'
+})
+export class TableExampleComponent {
+ public constructor(private dragulaService:DragulaService) {
+ dragulaService.setOptions('table-bag', {
+ revertOnSpill: true
+ });
+ }
+}
+
+@Component({
+ selector: 'table-example-child',
+ template: `
+
+
+
+
+ Name
+ Status
+
+
+
+
+
+ Tester
+ Active
+
+
+
+ James
+ Active
+
+
+
+ Alex
+ Active
+
+
+
`
+})
+export class TableChildExampleComponent {
+ public constructor() {
+ }
+}
+
export const EXAMPLES:any[] = [
ExampleAComponent,
ExampleBComponent,
@@ -203,5 +250,7 @@ export const EXAMPLES:any[] = [
MuchExampleComponent,
WowExampleComponent,
RepeatExampleComponent,
- NestedRepeatExampleComponent
+ NestedRepeatExampleComponent,
+ TableExampleComponent,
+ TableChildExampleComponent
];
diff --git a/demo/src/app/templates/table-example.html b/demo/src/app/templates/table-example.html
new file mode 100644
index 00000000..52e41964
--- /dev/null
+++ b/demo/src/app/templates/table-example.html
@@ -0,0 +1,46 @@
+
+
Move table rows when dont have access to child elements
+
+
+
+<table-example-child [dragula]='"table-bag"' [dragulaOptions]="{{'{'}} childContainerSelector: 'tbody', initAfterView: true {{'}'}}">
+</table-example-child>
+
+Component(
+ selector: 'table-example-child',
+ template: `
+ <table>
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Status</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Tester</td>
+ <td>Active</td>
+ </tr>
+ <tr>
+ <td>James</td>
+ <td>Active</td>
+ </tr>
+ <tr>
+ <td>Alex</td>
+ <td>Active</td>
+ </tr>
+ </tbody>
+ </table>`
+)
+export class TableChildExampleComponent
+ public constructor()
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/src/assets/css/example.css b/demo/src/assets/css/example.css
index c4f740a3..b86cd902 100644
--- a/demo/src/assets/css/example.css
+++ b/demo/src/assets/css/example.css
@@ -1,181 +1,244 @@
body {
- background-color: #942A57;
- margin: 0 auto;
- max-width: 760px;
+ background-color: #942A57;
+ margin: 0 auto;
+ max-width: 760px;
}
-html, body {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
+html,
+body {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
}
-*, *:before, *:after {
- -webkit-box-sizing: inherit;
- -moz-box-sizing: inherit;
- box-sizing: inherit;
+*,
+*:before,
+*:after {
+ -webkit-box-sizing: inherit;
+ -moz-box-sizing: inherit;
+ box-sizing: inherit;
}
-body, input, button {
- font-family: Georgia, Helvetica;
- font-size: 17px;
- color: #ecf0f1;
+body,
+input,
+button {
+ font-family: Georgia, Helvetica;
+ font-size: 17px;
+ color: #ecf0f1;
}
h1 {
- text-align: center;
- background-color: #AC5C7E;
- margin-top: 20px;
- margin-bottom: 0;
- padding: 10px;
+ text-align: center;
+ background-color: #AC5C7E;
+ margin-top: 20px;
+ margin-bottom: 0;
+ padding: 10px;
}
h3 {
- background-color: rgba(255, 255, 255, 0.2);
- border-bottom: 5px solid #A13462;
- text-align: center;
- padding: 10px;
+ background-color: rgba(255, 255, 255, 0.2);
+ border-bottom: 5px solid #A13462;
+ text-align: center;
+ padding: 10px;
}
h3 div {
- margin-bottom: 10px;
+ margin-bottom: 10px;
}
.tagline {
- margin-top: 0;
+ margin-top: 0;
}
.promo {
- margin-bottom: 0;
- font-style: italic;
- padding: 10px;
- background-color: #ff4020;
- border-bottom: 5px solid #c00;
+ margin-bottom: 0;
+ font-style: italic;
+ padding: 10px;
+ background-color: #ff4020;
+ border-bottom: 5px solid #c00;
}
a {
- font-weight: bold;
+ font-weight: bold;
}
+
a,
a:hover {
- color: #ecf0f1;
+ color: #ecf0f1;
}
pre {
- white-space: pre-wrap;
+ white-space: pre-wrap;
}
pre code {
- color: #fff;
- font-size: 14px;
- line-height: 1.3;
+ color: #fff;
+ font-size: 14px;
+ line-height: 1.3;
}
label {
- display: block;
- margin-bottom: 15px;
+ display: block;
+ margin-bottom: 15px;
}
sub {
- display: block;
- margin-top: -10px;
- margin-bottom: 15px;
- font-size: 11px;
- font-style: italic;
+ display: block;
+ margin-top: -10px;
+ margin-bottom: 15px;
+ font-size: 11px;
+ font-style: italic;
}
ul {
- margin: 0;
- padding: 0;
+ margin: 0;
+ padding: 0;
}
.parent {
- background-color: rgba(255, 255, 255, 0.2);
- margin: 50px 0;
- padding: 20px;
+ background-color: rgba(255, 255, 255, 0.2);
+ margin: 50px 0;
+ padding: 20px;
}
input {
- border: none;
- outline: none;
- background-color: #ecf0f1;
- padding: 10px;
- color: #942A57;
- border: 0;
- margin: 5px 0;
- display: block;
- width: 100%;
+ border: none;
+ outline: none;
+ background-color: #ecf0f1;
+ padding: 10px;
+ color: #942A57;
+ border: 0;
+ margin: 5px 0;
+ display: block;
+ width: 100%;
}
button {
- background-color: #ecf0f1;
- color: #942A57;
- border: 0;
- padding: 18px 12px;
- margin-left: 6px;
- cursor: pointer;
- outline: none;
+ background-color: #ecf0f1;
+ color: #942A57;
+ border: 0;
+ padding: 18px 12px;
+ margin-left: 6px;
+ cursor: pointer;
+ outline: none;
}
button:hover {
- background-color: #e74c3c;
- color: #ecf0f1;
+ background-color: #e74c3c;
+ color: #ecf0f1;
}
.gh-fork {
- position: fixed;
- top: 0;
- right: 0;
- border: 0;
+ position: fixed;
+ top: 0;
+ right: 0;
+ border: 0;
}
+
/* dragula-specific example page styles */
+
.wrapper {
- display: table;
+ display: table;
}
+
.container {
- display: table-cell;
- background-color: rgba(255, 255, 255, 0.2);
- width: 50%;
+ display: table-cell;
+ background-color: rgba(255, 255, 255, 0.2);
+ width: 50%;
}
+
.container:nth-child(odd) {
- background-color: rgba(0, 0, 0, 0.2);
+ background-color: rgba(0, 0, 0, 0.2);
}
+
+
/*
* note that styling gu-mirror directly is a bad practice because it's too generic.
* you're better off giving the draggable elements a unique class and styling that directly!
*/
+
.container div,
.gu-mirror {
- margin: 10px;
- padding: 10px;
- background-color: rgba(0, 0, 0, 0.2);
- transition: opacity 0.4s ease-in-out;
+ margin: 10px;
+ padding: 10px;
+ background-color: rgba(0, 0, 0, 0.2);
+ transition: opacity 0.4s ease-in-out;
}
+
.container div {
- cursor: move;
- cursor: grab;
- cursor: -moz-grab;
- cursor: -webkit-grab;
+ cursor: move;
+ cursor: grab;
+ cursor: -moz-grab;
+ cursor: -webkit-grab;
}
+
.gu-mirror {
- cursor: grabbing;
- cursor: -moz-grabbing;
- cursor: -webkit-grabbing;
+ cursor: grabbing;
+ cursor: -moz-grabbing;
+ cursor: -webkit-grabbing;
}
+
.container .ex-moved {
- background-color: #e74c3c;
+ background-color: #e74c3c;
}
+
.container.ex-over {
- background-color: rgba(255, 255, 255, 0.3);
+ background-color: rgba(255, 255, 255, 0.3);
}
+
.handle {
- padding: 0 5px;
- margin-right: 5px;
- background-color: rgba(0, 0, 0, 0.4);
- cursor: move;
+ padding: 0 5px;
+ margin-right: 5px;
+ background-color: rgba(0, 0, 0, 0.4);
+ cursor: move;
}
+
nested-repeat-example .container span {
- display: block;
- padding: 8px;
+ display: block;
+ padding: 8px;
+}
+
+.table {
+ color: #333;
+ /* Lighten up font color */
+ font-family: Helvetica, Arial, sans-serif;
+ /* Nicer font */
+ width: 300px;
+ border-collapse: collapse;
+ border-spacing: 0;
}
+
+.table td,
+.table th {
+ border: 1px solid #CCC;
+ height: 30px;
+}
+
+
+/* Make cells a bit taller */
+
+.table th {
+ background: #F3F3F3;
+ /* Light grey background */
+ font-weight: bold;
+ /* Make sure they're bold */
+}
+
+.table td {
+ background: #FAFAFA;
+ /* Lighter grey background */
+ text-align: center;
+ /* Center our text */
+}
+
+.table .bars {
+ background-image: url(data:image/png;base64,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);
+ background-repeat: no-repeat;
+ background-size: 16px 16px;
+ width: 16px;
+ color: #000;
+ height: 16px;
+ margin: 0 auto;
+ cursor: move;
+}
\ No newline at end of file
diff --git a/src/components/dragula.directive.ts b/src/components/dragula.directive.ts
index b9a7e579..abac8a93 100644
--- a/src/components/dragula.directive.ts
+++ b/src/components/dragula.directive.ts
@@ -1,14 +1,15 @@
-import { Directive, Input, ElementRef, OnInit, OnChanges, SimpleChange } from '@angular/core';
+import { Directive, Input, ElementRef, OnInit, AfterViewInit, OnChanges, SimpleChange } from '@angular/core';
import { DragulaService } from './dragula.provider';
import { dragula } from './dragula.class';
@Directive({selector: '[dragula]'})
-export class DragulaDirective implements OnInit, OnChanges {
+export class DragulaDirective implements OnInit, OnChanges, AfterViewInit {
@Input() public dragula: string;
@Input() public dragulaModel: any;
@Input() public dragulaOptions: any;
- private container: any;
+ protected container: any; //allows for extension
private drake: any;
+ private options: any;
private el: ElementRef;
private dragulaService: DragulaService;
@@ -19,7 +20,38 @@ export class DragulaDirective implements OnInit, OnChanges {
}
public ngOnInit(): void {
- // console.log(this.bag);
+ this.options = Object.assign({}, this.dragulaOptions);
+ this.container = this.el.nativeElement;
+ if(!this.options.initAfterView){
+ this.initialize();
+ }
+ }
+
+ ngAfterViewInit() {
+ if(this.options.initAfterView){
+ this.initialize();
+ }
+ }
+
+ public ngOnChanges(changes: {dragulaModel?: SimpleChange}): void {
+ if (changes && changes.dragulaModel) {
+ if (this.drake) {
+ if (this.drake.models) {
+ let modelIndex = this.drake.models.indexOf(changes.dragulaModel.previousValue);
+ this.drake.models.splice(modelIndex, 1, changes.dragulaModel.currentValue);
+ } else {
+ this.drake.models = [changes.dragulaModel.currentValue];
+ }
+ }
+ }
+ }
+
+ protected initialize(){
+ if(this.options.childContainerSelector){
+ this.container = this.el.nativeElement.querySelector(this.options.childContainerSelector);
+ this.options.mirrorContainer = this.container;
+ }
+
let bag = this.dragulaService.find(this.dragula);
let checkModel = () => {
if (this.dragulaModel) {
@@ -35,24 +67,9 @@ export class DragulaDirective implements OnInit, OnChanges {
checkModel();
this.drake.containers.push(this.container);
} else {
- this.drake = dragula([this.container], Object.assign({}, this.dragulaOptions));
+ this.drake = dragula([this.container], this.options);
checkModel();
this.dragulaService.add(this.dragula, this.drake);
}
}
-
- public ngOnChanges(changes: {dragulaModel?: SimpleChange}): void {
- // console.log('dragula.directive: ngOnChanges');
- // console.log(changes);
- if (changes && changes.dragulaModel) {
- if (this.drake) {
- if (this.drake.models) {
- let modelIndex = this.drake.models.indexOf(changes.dragulaModel.previousValue);
- this.drake.models.splice(modelIndex, 1, changes.dragulaModel.currentValue);
- } else {
- this.drake.models = [changes.dragulaModel.currentValue];
- }
- }
- }
- }
}