Elegant way to apply jquery plugin in Angular2 - javascript

I fetch data from webservice in ngOnInit block and then i need to apply jquery data table plugin (this action i performed both in ngAfterViewInit and ngAfterContentInit). The problem is that jquery datatable plugin don't see data in the component table which was fetched in ngOnInit block. The only way I could implement this is setTimeout or setInterval (which stops execution if plugin instance created).
Is there any other method to perform task I try to ?
export class DataTable implements OnInit, AfterViewInit, AfterContentInit, AfterContentChecked {
public data = null;
public table = null;
constructor(public translate: TranslateService, public ngZone: NgZone) {
}
ngOnInit(): void {
this.translate.getData().subscribe((records) => {
this.data = records;
});
}
ngAfterViewInit(): void {
this.dataTableDynamicUpdater();
}
ngAfterContentInit() : void {
}
ngAfterContentChecked() {
}
dataTableDynamicUpdater() {
let self = this;
let interval = setInterval(() => {
if(self.data) {
self.instantiateDataTable();
clearInterval(interval);
}
}, 200);
}
instantiateDataTable() {
let _FILTER_PLACEHOLDER_ = this.translate.instant('APP_DATATABLE_PLACEHOLDER_TYPE_TO_FILTER');
let _FILTER_LABEL_ = this.translate.instant('APP_DATATABLE_LABEL_FILTER');
let _SHOW_LABEL_ = this.translate.instant('APP_DATATABLE_LABEL_SHOW');
$.extend($.fn.dataTable.defaults, {
autoWidth: false,
dom: '<"datatable-header"fBl><"datatable-scroll-wrap"t><"datatable-footer"ip>',
language: {
search: '<span>_FILTER_LABEL_</span> _INPUT_',
lengthMenu: '<span>_SHOW_LABEL_</span> _MENU_',
paginate: { 'first': 'First', 'last': 'Last', 'next': '→', 'previous': '←' }
}
});
// Column selectors
let table = $('.table').DataTable({
buttons: {
buttons: [
{
extend: 'excelHtml5',
className: 'btn btn-default',
exportOptions: {
columns: ':visible'
}
}
]
}
});
// Add placeholder to the datatable filter option
$('.dataTables_filter input[type=search]').attr('placeholder', _FILTER_PLACEHOLDER_);
// Enable Select2 select for the length option
$('.dataTables_length select').select2({
minimumResultsForSearch: Infinity,
width: 'auto'
});
return table;
}
}

Try doing it after the data was fetched
ngOnInit(): void {
let self = this;
this.translate.getData().subscribe((records) => {
this.data = records;
self.instantiateDataTable();
});
}

Related

How to call a typescript arrow function and a javascript function in the same event

I want to call both a javascript function and a typescript function from the same event. It is a onClick event in a chart. I am relatively new to typescript and angular, so i dont know if what i am doing is even possible.
The problem is: I need to call a javascript function for getting a activated bar in the chart, and the typescript function to open a dialog in the angular component.
onClick: function(evt){
console.log(this);//<-- returns chart
bar: () => {console.log(this)}; //<-- here I try to get this as component
bar(); // <--doesnt work
//console.log(document.getElementById('myChart'));
}
Maybe bette if i show the whole thing.
public barChartOptions = {
scaleShowVerticalLines: false,
responsive: true,
events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
onHover: console.log('onHover'),
onClick: function(evt){
//console.log(evt); Mouse Event
console.log(this);
const getFirst = array => console.log(this);
console.log(getFirst);
//bar: () => {console.log(this)};
//bar();
//console.log(document.getElementById('myChart'));
},
/*
onClick : (evt, datasets) => {
//let self = this;
//console.log(self);
if(datasets.length > 0){
this.openDialog();
console.log(this);
console.log(this.barChart);
}
},*/
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
},
legend: {
display: true,
position: 'right'
},
tooltips: {
enabled: true,
mode: 'point'
}
};
this is my html template:
my-bar-dialog works!
<div>
<div style="display: block">
<canvas baseChart
id="myChart"
[datasets]="barChartData"
[labels]="barChartLabels"
[options]="barChartOptions"
[legend]="barChartLegend"
[chartType]="barChartType">
</canvas>
</div>
</div>
<button mat-raised-button (click)="openDialog()">Pick one</button>
<button (click)="openDialog()">Pick one</button>
Now, the thing is i have two different "this":
1)
onClick: function(evt){
let that = this;
let bar=()=> {console.log(that.this)};
bar();
},
2)
onClick : (evt, datasets) => {
if(datasets.length > 0){
console.log(this);
}
},
1 returns a char, 2 returns the component.
But i need both of them in the same Event/function as i need to call chartjs api functions and i need to call a function from my component.
And here my component
import { Component, OnInit, Inject } from '#angular/core';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '#angular/material/dialog';
import { BarChartService } from '../bar-chart.service';
import { barChartClass } from '../barChartClass';
declare var foo: Function;
#Component({
selector: 'app-my-bar-dialog',
templateUrl: './my-bar-dialog.component.html',
styleUrls: ['./my-bar-dialog.component.css'],
})
export class MyBarDialogComponent implements OnInit {
client: string;
tenant: string;
constructor(public dialog: MatDialog, private barChartService: BarChartService) {
foo();
}
//First BarChart
barChart: barChartClass;
public barChartLabels: any;
public barChartType: any;
public barChartLegend: any;
public barChartData: any;
getBarChart(): void {
this.barChartService.getMockBarChart().subscribe(
barChart => this.barChart = barChart
);
this.barChartData = this.barChart.barChartData;
this.barChartLabels = this.barChart.barChartLabels;
this.barChartType = this.barChart.barChartType;
this.barChartLegend = this.barChart.barChartLegend;
}
public barChartOptions = {
scaleShowVerticalLines: false,
responsive: true,
events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
onHover: console.log('onHover'),
onClick: function(evt){
//console.log(evt); Mouse Event
//console.log(this);
let that = this;
//bar: () => {console.log(this)};
let bar=()=> {console.log(that.this)};
bar();
//bar();
//console.log(document.getElementById('myChart'));
},
/*
onClick : (evt, datasets) => {
//let self = this;
//console.log(self);
if(datasets.length > 0){
this.openDialog();
console.log(this);
console.log(this.barChart);
}
},*/
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
},
legend: {
display: true,
position: 'right'
},
tooltips: {
enabled: true,
mode: 'point'
}
};
openDialog(): void {
const dialogRef = this.dialog.open(DialogData, {
width: '250px',
data: {client: this.client, tenant: this.tenant}
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
this.client = result;
});
}
ngOnInit() {
this.getBarChart();
}
}
#Component({
selector: 'dialog-data',
templateUrl: 'dialog-data.html',
styleUrls: ['dialog-data.css']
})
export class DialogData {
constructor(
public dialogRef: MatDialogRef<DialogData>,
#Inject(MAT_DIALOG_DATA) public data: DialogData) {}
onNoClick(): void {
this.dialogRef.close();
}
}
What you're doing with the bar and the colon in the function is that you're trying to describe its type rather to declare it. So if you want to actually declare the function, do this:
onClick: function(evt) {
console.log(this);//<-- returns chart
let bar = () => { console.log(this) };
bar();
//console.log(document.getElementById('myChart'));
}
if you want to describe and declare it, do this:
onClick: function(evt) {
console.log(this);//<-- returns chart
let bar: () => void = () => { console.log(this) }; //<-- here I try to get this as component
bar(); // <--doesnt work
//console.log(document.getElementById('myChart'));
}
before using the chart in component assign this to some other variable like
var that=this
then in your chart
onClick: function(evt){
console.log(this);//<-- returns chart
let bar= () => {console.log(that)}; //<-- that should have your component refrence
}
Stackblitz demo

Ag-Grid cellRender with Button Click

I am using an angular 5 with ag-grid data table
i cant able to trigger a click event from cell using cellRenderer here how am using my ag-grid --> colDefs
this.columnDefs = [
{headerName: '#', rowDrag: true, width: 75},
{headerName: 'One', field: 'fieldName',
cellRenderer : function(params){
return '<div><button (click)="drop()">Click</button></div>'
}
}
];
drop() {
alert("BUTTON CLICKEFD")
}
if am using onClick="alert("123")" --> it works,
but i cant able to use onClick="drop()" it throws drop of undefined,
i tried this too inside of cellRenderer --> params = params.$scope.drop = this.drop;
if am using gridOptions with angularCompileRows : true it throws an error Cannot read property '$apply' of undefined.
Do i need to install ag-grid enterprise ??
You can use cellRenderer with a button component.
If you want to get the click event on the button from the user on the table, just declare the callback function you want to cellRendererParams.
// app.component.ts
columnDefs = [
{
headerName: 'Button Col 1',
cellRenderer: 'buttonRenderer',
cellRendererParams: {
onClick: this.onBtnClick.bind(this),
label: 'Click'
}
},
...
]
The above code is just a small part, check out full example on Stackblitz
Angular.
Here we create the button cell renderer as an Angular component that implements the ICellRendererAngularComp interface. Access to the params object can be found on the agInit hook.
// app/button-cell-renderer.component.ts
#Component({
selector: 'btn-cell-renderer',
template: `
<button (click)="btnClickedHandler($event)">Click me!</button>
`,
})
export class BtnCellRenderer implements ICellRendererAngularComp, OnDestroy {
private params: any;
agInit(params: any): void {
this.params = params;
}
btnClickedHandler() {
this.params.clicked(this.params.value);
}
ngOnDestroy() {
// no need to remove the button click handler as angular does this under the hood
}
}
The renderer is registered to ag-Grid via gridOptions.frameworkComponents. Note that we’re passing the button click handler dynamically to our renderer via cellRendererParams - allowing for a more flexible and reusable renderer.
// app/app.component.ts
this.columnDefs = [
{
field: 'athlete',
cellRenderer: 'btnCellRenderer',
cellRendererParams: {
clicked: function(field: any) {
alert(`${field} was clicked`);
}
},
minWidth: 150,
}
// [...]
];
this.frameworkComponents = {
btnCellRenderer: BtnCellRenderer
};
It is also necessary to pass our renderer to our #NgModule decorator to allow for dependency injection.
// app/app.modules.ts
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
AgGridModule.withComponents([BtnCellRenderer]),
],
declarations: [AppComponent, BtnCellRenderer],
bootstrap: [AppComponent],
})
See demo.
Learn more about Angular Cell Renderer.
Vanilla JavaScript.
A DOM element is created in the init method, which is then returned in the getGui method. The optional destroy hook has also included to do some cleanup (removing the click listener from our component).
// btn-cell-renderer.js
function BtnCellRenderer() {}
BtnCellRenderer.prototype.init = function(params) {
this.params = params;
this.eGui = document.createElement('button');
this.eGui.innerHTML = 'Click me!';
this.btnClickedHandler = this.btnClickedHandler.bind(this);
this.eGui.addEventListener('click', this.btnClickedHandler);
}
BtnCellRenderer.prototype.getGui = function() {
return this.eGui;
}
BtnCellRenderer.prototype.destroy = function() {
this.eGui.removeEventListener('click', this.btnClickedHandler);
}
BtnCellRenderer.prototype.btnClickedHandler = function(event) {
this.params.clicked(this.params.value);
}
The renderer is registered to ag-Grid in gridOptions.components and is used on the athlete column. Note that we’re passing the button click handler dynamically to our renderer via cellRendererParams - this makes for a more flexible and reusable renderer.
// main.js
var gridOptions = {
columnDefs: [
{
field: 'athlete',
cellRenderer: 'btnCellRenderer',
cellRendererParams: {
clicked: function(field) {
alert(`${field} was clicked`);
}
},
minWidth: 150
},
// [...]
components: {
btnCellRenderer: BtnCellRenderer
}
};
See demo.
Learn more about JavaScript Cell Renderers.
React.
Here our button cell renderer is constructed as a React component. The only thing to take note of here is that cell params will be available on the component via props.
// BtnCellRenderer.jsx
class BtnCellRenderer extends Component {
constructor(props) {
super(props);
this.btnClickedHandler = this.btnClickedHandler.bind(this);
}
btnClickedHandler() {
this.props.clicked(this.props.value);
}
render() {
return (
<button onClick={this.btnClickedHandler}>Click Me!</button>
)
}
}
The renderer is registered to ag-Grid via gridOptions.frameworkComponents. The button click handler is passed to our renderer at run time via cellRendererParams - allowing for a more flexible and reusable renderer.
// index.jsx
columnDefs: [
{
field: 'athlete',
cellRenderer: 'btnCellRenderer',
cellRendererParams: {
clicked: function(field) {
alert(`${field} was clicked`);
},
},
// [...]
}
];
frameworkComponents: {
btnCellRenderer: BtnCellRenderer,
}
See demo.
Learn more about React Cell Renderers.
Vue.js.
Configuring the renderer in Vue.js is simple:
// btn-cell-renderer.js
export default Vue.extend({
template: `
<span>
<button #click="btnClickedHandler()">Click me!</button>
</span>
`,
methods: {
btnClickedHandler() {
this.params.clicked(this.params.value);
}
},
});
As with the other frameworks, the renderer is registered to ag-Grid via gridOptions.frameworkComponents and the button click handler is passed to our renderer at run time via cellRendererParams - allowing for a more flexible and reusable renderer.
// main.js
this.columnDefs = [
{
field: 'athlete',
cellRenderer: 'btnCellRenderer',
cellRendererParams: {
clicked: function(field) {
alert(`${field} was clicked`);
}
},
// [...]
],
this.frameworkComponents = {
btnCellRenderer: BtnCellRenderer
}
See demo.
Learn more about Vue.js Cell Renderers.
Read the full blog post on our website or check out our documentation for a great variety of scenarios you can implement with ag-Grid.
Ahmed Gadir | Developer # ag-Grid
To expand on the answer from #T4professor, I will post some code to also have a dynamic label on that Click button.
// Author: T4professor
import { Component, OnInit, AfterContentInit } from '#angular/core';
import { ICellRendererAngularComp } from 'ag-grid-angular';
#Component({
selector: 'app-button-renderer',
template: `
<button class="{{btnClass}}" type="button" (click)="onClick($event)">{{label}}</button>
`
})
export class ButtonRendererComponent implements ICellRendererAngularComp {
//https://stackblitz.com/edit/angular-ag-grid-button-renderer?file=src%2Fapp%2Fapp.component.ts
params: any;
label: string;
getLabelFunction: any;
btnClass: string;
agInit(params: any): void {
this.params = params;
this.label = this.params.label || null;
this.btnClass = this.params.btnClass || 'btn btn-primary';
this.getLabelFunction = this.params.getLabelFunction;
if(this.getLabelFunction && this.getLabelFunction instanceof Function)
{
console.log(this.params);
this.label = this.getLabelFunction(params.data);
}
}
refresh(params?: any): boolean {
return true;
}
onClick($event) {
if (this.params.onClick instanceof Function) {
// put anything into params u want pass into parents component
const params = {
event: $event,
rowData: this.params.node.data
// ...something
}
this.params.onClick(params);
}
}
}
Then, in the component with the grid you do the following:
columnDefs = [
{
headerName: 'Publish',
cellRenderer: 'buttonRenderer',
cellRendererParams: {
onClick: this.onRowPublishBtnClick.bind(this),
label: 'Publish',
getLabelFunction: this.getLabel.bind(this),
btnClass: 'btn btn-primary btn-sm'
}
}
]
onRowPublishBtnClick(e) {
this.rowDataClicked = e.rowData;
}
getLabel(rowData)
{
console.log(rowData);
if(rowData && rowData.hasIndicator)
return 'Republish';
else return 'Publish';
}
You have this issue because you invoke drop() incorrectly you should change it to this.drop()
In general you should use cellRenderer property with simple logic. More convenient way for complex logic renderer you should use cellRendererFramework: YourCustomRendererAngularComponent.
columnDefs = [
{
headerName: 'Col Name',
cellRendererFramwork: MyAngularRendererComponent, // RendererComponent suffix it is naming convention
cellRendererParams: {
onClick: (params) => this.click(params);
}
},
...
]
MyAngularRendererComponent should implements AgRendererComponent.
Also in angular module where you use MyAngualrRendererComponent don`t forget put this code:
#NgModule({
imports: [
AgGridModule.withCompoennts([
MyAngualrRendererComponent
])
]
})
I was looking for a solution to this but for multiple buttons in the same column. I couldn't find an answer anywhere so I wrote up this Plain Javascript solution. I hope it helps other people looking for the solution I was looking for. Also open to suggestions on how to make the javascript less hacky.
// multi-btn-cell-renderer.js
function multiBtnCellRenderer() {}
multiBtnCellRenderer.prototype.init = function(params) {
var self = this;
self.params = params;
self.num_buttons = parseInt(this.params.num_buttons);
self.btnClickedHandlers = {};
let outerDiv = document.createElement('div')
for(let i = 0; i < self.num_buttons; i++) {
let button = document.createElement('button');
button.innerHTML = self.params.button_html[i];
outerDiv.appendChild(button);
self.btnClickedHandlers[i] = function(event) {
self.params.clicked[i](self.params.get_data_id());
}.bind(i, self);
button.addEventListener('click', self.btnClickedHandlers[i]);
}
self.eGui = outerDiv;
};
multiBtnCellRenderer.prototype.getGui = function() {
return this.eGui;
};
multiBtnCellRenderer.prototype.destroy = function() {
for(let i = 0; i < this.num_buttons; i++) {
this.eGui.removeEventListener('click', this.btnClickedHandlers[i]);
}
};
// main.js
var columnDefs = [
{
headerName: "Action",
maxWidth: 60,
filter: false,
floatingFilter: false,
suppressMenu: true,
sortable: false,
cellRenderer: multiBtnCellRenderer,
cellRendererParams: {
num_buttons: 2,
button_html: ["<i class='fa fa-pencil'></i>","<i class='fa fa-trash'></i>"],
get_data_id: function() {
return this.data.id;
},
clicked: {
0: function(data_id) {
$.get(`/employee/${data_id}/edit`)
},
1: function(data_id) {
$.delete(`/employee/${data_id}`)
}
}
}
}
]

Angular create Dynamic Component recursively

I am trying to build a dynamic component based on a Config. The component would read the config recursively and create the component. It is found that the method ngAfterViewInit() would only be called twice.
#Component({
selector: "dynamic-container-component",
template: `
<div #container
draggable="true"
(dragstart)="dragstart($event)"
(drop)="drop($event)"
(dragover)="dragover($event)"
style="border: 1px solid; min-height: 30px"></div>
`
})
export default class DynamicContainerComponent {
#Input()
dynamicConfig: DynamicConfig;
#ViewChild("container", {read: ElementRef})
private elementRef: ElementRef;
private isContainer: boolean;
private componentRef: ComponentRef<any>;
private componentRefs: ComponentRef<any>[] = [];
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
private viewContainer: ViewContainerRef,
private render: Renderer2
){
console.log("running");
}
ngAfterViewInit(){
if (this.dynamicConfig){
console.log(this.dynamicConfig)
if (this.dynamicConfig.getType() == ComponentType.INPUT){
this.isContainer = false;
let componetFactory: ComponentFactory<InputComponent> =
this.componentFactoryResolver.resolveComponentFactory(InputComponent);
this.componentRef = this.viewContainer.createComponent(componetFactory);
this.render.appendChild(this.elementRef.nativeElement, this.componentRef.location.nativeElement);
}else {
this.isContainer = true;
let items: DynamicConfig[] = this.dynamicConfig.getItems();
if (items){
for (var i=0; i<items.length; i++){
let item: DynamicConfig = items[i];
let componetFactory: ComponentFactory<DynamicContainerComponent> =
this.componentFactoryResolver.resolveComponentFactory(DynamicContainerComponent);
let componentRef: ComponentRef<DynamicContainerComponent> =
this.viewContainer.createComponent(componetFactory);
componentRef.instance.dynamicConfig = item;
this.componentRefs.push(componentRef);
this.render.appendChild(this.elementRef.nativeElement, componentRef.location.nativeElement);
}
}
}
}else {
console.log("config does not exist");
}
}
dragstart(event){
debugger;
}
drop(event){
debugger;
}
dragover(event){
debugger;
event.preventDefault();
}
}
The Component would be created by other component by the following code. If The Dynamic Component would create another Dynamic Component by componentFactoryResolver.
var configJson = {
type: ComponentType.CONTAINER,
items: [
{
type: ComponentType.CONTAINER,
items: [{
type: ComponentType.CONTAINER,
items: [{
type: ComponentType.CONTAINER,
items: [{
type: ComponentType.INPUT
}]
}]
}]
}
]
}
this.config = new DynamicConfig();
this.config.assign(configJson);
console.log(this.config);
Update
I found a similar issue in github: https://github.com/angular/angular/issues/10762
I have done something suggested by other people. but I think it is just a dirty fix.
ngAfterViewInit(){
setTimeout(function(){
if (this.dynamicConfig){
console.log(this.dynamicConfig)
if (this.dynamicConfig.getType() == ComponentType.INPUT){
this.isContainer = false;
let componetFactory: ComponentFactory<InputComponent> =
this.componentFactoryResolver.resolveComponentFactory(InputComponent);
this.componentRef = this.viewContainer.createComponent(componetFactory);
this.render.appendChild(this.elementRef.nativeElement, this.componentRef.location.nativeElement);
}else {
this.isContainer = true;
let items: DynamicConfig[] = this.dynamicConfig.getItems();
if (items){
for (var i=0; i<items.length; i++){
let item: DynamicConfig = items[i];
let componetFactory: ComponentFactory<DynamicContainerComponent> =
this.componentFactoryResolver.resolveComponentFactory(DynamicContainerComponent);
let componentRef: ComponentRef<DynamicContainerComponent> =
this.viewContainer.createComponent(componetFactory);
componentRef.instance.dynamicConfig = item;
this.componentRefs.push(componentRef);
this.render.appendChild(this.elementRef.nativeElement, componentRef.location.nativeElement);
}
}
}
}else {
console.log("config does not exist");
}
}.bind(this))
}
By the time you create your dynamic component angular has almost finished change detection cycle.
This way you can either run:
componentRef.changeDetectorRef.detectChanges()
Note: setTimeout has similar effect but fires change detection cycle on the whole app
or rename lifecycle hook to ngOnInit
Also you're passing wrong input to dynamic component:
let item: DynamicConfig = items[i];
^^^^^^^^^^^^^
but it is not DynamicConfig instance but rather plain object
...
componentRef.instance.dynamicConfig = item;
it should be:
let item: any = items[i];
const config = new DynamicConfig();
config.assign(item);
componentRef.instance.dynamicConfig = config;
Ng-run Example

How to implement drag-drop directive for Ionic?

//long-press.directive.d.ts
import { ElementRef, EventEmitter, OnDestroy, OnInit, NgZone } from '#angular/core';
import { Gesture } from 'ionic-angular/gestures/gesture';
export declare class LongPressDirective implements OnInit, OnDestroy {
zone: NgZone;
interval: number;
onPressStart: EventEmitter<any>;
onPressing: EventEmitter<any>;
onPressEnd: EventEmitter<any>;
el: HTMLElement;
pressGesture: Gesture;
int: any;
constructor(zone: NgZone, el: ElementRef);
ngOnInit(): void;
ngOnDestroy(): void;
}
//long-press.drective.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var core_1 = require("#angular/core");
var gesture_1 = require("ionic-angular/gestures/gesture");
var LongPressDirective = (function () {
function LongPressDirective(zone, el) {
this.zone = zone;
this.onPressStart = new core_1.EventEmitter();
this.onPressing = new core_1.EventEmitter();
this.onPressEnd = new core_1.EventEmitter();
this.el = el.nativeElement;
}
LongPressDirective.prototype.ngOnInit = function () {
var _this = this;
if (!this.interval)
this.interval = 500;
if (this.interval < 40) {
throw new Error('A limit of 40ms is imposed so you don\'t destroy device performance. If you need less than a 40ms interval, please file an issue explaining your use case.');
}
this.pressGesture = new gesture_1.Gesture(this.el);
this.pressGesture.listen();
this.pressGesture.on('press', function (e) {
_this.onPressStart.emit(e);
_this.zone.run(function () {
_this.int = setInterval(function () {
_this.onPressing.emit();
}, _this.interval);
});
});
this.pressGesture.on('pressup', function (e) {
_this.zone.run(function () {
clearInterval(_this.int);
});
_this.onPressEnd.emit();
});
};
LongPressDirective.prototype.ngOnDestroy = function () {
var _this = this;
this.zone.run(function () {
clearInterval(_this.int);
});
this.onPressEnd.emit();
this.pressGesture.destroy();
};
return LongPressDirective;
}());
LongPressDirective.decorators = [
{ type: core_1.Directive, args: [{
selector: '[ion-long-press]'
},] },
];
/** #nocollapse */
LongPressDirective.ctorParameters = function () { return [
{ type: core_1.NgZone, },
{ type: core_1.ElementRef, },
]; };
LongPressDirective.propDecorators = {
'interval': [{ type: core_1.Input },],
'onPressStart': [{ type: core_1.Output },],
'onPressing': [{ type: core_1.Output },],
'onPressEnd': [{ type: core_1.Output },],
};
exports.LongPressDirective = LongPressDirective;
//# sourceMappingURL=long-press.directive.js.map
This is implementation of 'press', 'press-up' event.
This directive intends to build upon the existing Hammer.JS press event that Ionic uses for long pressing, by giving you interval emission.
https://www.npmjs.com/package/ionic-long-press
I want to add 'drag'-'drop' event.
I am beginner of angular.
Expert's help is needed.
Thanks.
I solved the problem using this plugin.
https://github.com/AbineshSrishti/ionic2-selection-card-drag

JavaScript Callback After SilverStripe Grid Field Extensions Reorder?

I have a ModelAdmin with MyDataObject has_many AnotherDataObject and SilverStripe Grid Field Extensions Module that is controlling the
class TestAdmin extends ModelAdmin {
static $managed_models = array('MyDataObject');
static $url_segment = 'testadmin';
static $menu_title = 'TestAdmin';
}
class MyDataObject extends DataObject {
private static $db = array('Name' => 'Varchar(255)');
private static $has_many= array('AnotherDataObjects' => 'AnotherDataObject');
function getCMSFields() {
$fields = parent::getCMSFields();
if ($grid = $fields->dataFieldByName('AnotherDataObjects')) {
$grid->getConfig()
->removeComponentsByType('GridFieldAddExistingAutocompleter')
->addComponent(new GridFieldOrderableRows('Priority'));
$fields->removeByName('AnotherDataObjects');
$fields->insertAfter($grid,'Name');
}
return $fields;
}
}
class AnotherDataObject extends DataObject {
private static $db = array(
'Name' => 'Varchar(255)',
'Priority' => 'Int'
);
private static $has_one = array('MyDataObject' => 'MyDataObject');
}
I can see that the "reorder" is called, how would I attach, for example...
alert('Reorder Complete!');
...to be called once the system is finished with the database changes?
There are no events triggered when a grid rows have been reordered. However you can redefine the constructor:
$(".ss-gridfield-orderable tbody").entwine({
onadd: function() {
var self = this;
var helper = function(e, row) {
return row.clone()
.addClass("ss-gridfield-orderhelper")
.width("auto")
.find(".col-buttons")
.remove()
.end();
};
var update = function(event, ui) {
// If the item being dragged is unsaved, don't do anything
var postback = true;
if (ui.item.hasClass('ss-gridfield-inline-new')) {
postback = false;
}
// Rebuild all sort hidden fields
self.rebuildSort();
// Check if we are allowed to postback
var grid = self.getGridField();
if (grid.data("immediate-update") && postback)
{
grid.reload({
url: grid.data("url-reorder")
}, function(data) {
self.onreordered();
});
}
else
{
var form = $('.cms-edit-form');
form.addClass('changed');
}
};
this.sortable({
handle: ".handle",
helper: helper,
opacity: .7,
update: update
});
},
onreordered: function() {
console.log('The grid was reordered');
},
});
It should be loaded after GridFieldExtensions.js

Categories