yii efullcalendar widget and external events drag and drop not working - yii

Hi I am trying to use drag and drop external events for fullcalendar and get working with the yii extension full calender - which seems to be just a wrapper.
The part that is not working (no errors just does not work) is dragging the external event onto the calendar and it staying there. It drags over but it just returns home.
Reading the fullcalendar docs - it looks like I need to provide a callback function to 'drop' attribute. I've been using the external-event example which is part of full calendar. I did discover the example was using the object name '#calendar' and that yii is creating name '#yw0' but it still didn't work after I updated.
I cannot find a way to get it work. I tried a simple alert which sort of works, it is called on page load - not after a drag operation.
So I declared a variable with the function in View
//$dropcallback=new CJavaScriptExpression("alert('hi')");
$dropcallback=new CJavaScriptExpression(
"function(date, allDay) {
var originalEventObject = $(this).data('eventObject');
var copiedEventObject = $.extend({}, originalEventObject);
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
$('#yw0').fullCalendar('renderEvent', copiedEventObject, true);
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the Draggable Events list
$(this).remove();
}
}
");
Then I create the widgit like this
$this->widget('ext.EFullCalendar.EFullCalendar', array(
'themeCssFile'=>'cupertino/jquery-ui.min.css',
'options'=>array(
'header'=>array(
'left'=>'prev,next',
'center'=>'title',
'right'=>'today'
),
'editable'=>true,
'dropable'=>true,
'drop'=>$dropcallback,
'events'=>Game::model()->gameCalendarData(),
)));
My yii experiance is little and same with JS - so any help appreciated in how to get this working.
I understand that in JS you need to provide a callback to allow the drag op to succeed. But what sort of call back do I need when it is wrapped in a yii widgit? I tried a PHP callback and again it is only called on page load.
The result I wish is that I can build the external events list from the DB - allow users to drag them onto the calendar - and save them in the DB.
I did manage to get data from DB displayed in the calendar.
Thanks

Droppable is spelt with two p's. So
'dropable'=>true,
Should be
'droppable'=>true,

Related

Revive/activate existing panels

My extension have sidebar webview that can create additional webviews as panels in the active text editor. Each of these additional webviews is for an unique item and I want to revive/activate existing webview, for the specific item, if it exists.
My issues:
I can get a list of the existing tabs with window.tabGroups.all and loop through the result. But there is no way, as far as i can see, to reactivate the desired tab. I can get some properties from there but no methods. The question here is: is there a API to get a list of the tabs and be able to revive/activate it?
Because of the first point ive decided to keep list of the instances of the additional webviews and when new webview is about the be created im checking if its unique id (in the title) is in the list and if it is then just revive the tab instead of creating a new one. Dont like this approach much but its working. The problem here is when the additional webview is closed. When closed it has to be removed from the array. Ive implemented onDidDispose for the panel but somehow the filter function, inside it, is not called:
// panels: vscode.WebviewPanel[]
// create new panel
const panel = vscode.window.createWebviewPanel(...)
// add the webview instance to the panel
const newWebview = new AdditionalWebview(panel, this.context);
this.panels.push(panel);
panel.onDidDispose(() => {
console.log("Before remove the panel"); // can see this in the console
this.panels = this.panels.filter((p) => p.title != panel.title);
console.log("Before remove the panel"); // for some reason this never appears
});
Not sure why but the panel filter functionality is never triggered (and everything after it is also not ran).
extra question: at the moment the uniqueness of the additional panels is based on their label/title. In my case thats is ok but is there any other way to get unique identifier of each tab? id/guid somewhere?
On your first question about activating a given editor, you have a couple of options.
If you know the editor's index/position in its group. That can be obtained from its tabGroup.tabs position - it seems that the tab's index in that array is faithfully its index in the editor. So you could do a Array.findIndex to get the tab uri you want to set to active.
await vscode.commands.executeCommand('workbench.action.openEditorAtIndex', [indexToOpen]);
// note the [] around the index argument
The only problem with this approach is that it works within the active group only, so you may have to activate the correct group first via:
await vscode.commands.executeCommand('workbench.action.focusSecondEditorGroup');
// or whichever group the tab you want to open is in
Or second method:
// assumes you have the tab
const openOptions = { preserveFocus: true, preview: tab.isPreview, viewColumn: tab.group.viewColumn};
// check if a uri, might be viewtype, etc., instead
if (tab.input instanceof vscode.TabInputText) {
await vscode.commands.executeCommand('vscode.open', tab.input.uri, openOptions);
}
// are your editors regular text editors?
This looks like it is opening a new tab but it will focus an existing tab if one exists at that location with that same uri.

Aurelia Validation and event publish not updating values in View

I was using Event aggregate publish method to update view from another view. when I created publish and subscribe data was able to get in view model , but that is not updating in view with assigned variables. If I use JavaScript to fill value it's working but not able to trigger validate controller.
Expected result is:
From the subscribe method I have to fill the view values.
After that it should trigger validate on value changes.
In below gist run I have two view and view-model. One is registration-form and second one is data-form. In data-form I have table with data, on click of each row I am publishing one event with selected row data, and this published event I was subscribing in side of registration-form view-modal. For more details look into below gist run.
Gist run: https://gist.run/?id=8416e8ca1b9b5ff318b79ec94fd3220c
Two possible solutions: (to your "undefined" alert)
Change alert(this.email); to alert(myself.email);
Use the thick arrow syntax for the subscribe function. Change:
this.ea.subscribe('MyrowData', function(obj){
to
this.ea.subscribe('MyrowData', obj => {
This syntax allows the new function to preserve the context/scope of the parent, which means that this.email will still be accessible.
Another suggestion:
You could simplify your data-form.js function as follows:
Change:
this.eventAggregator.publish('MyrowData', this.items[this.items.indexOf(item)]);
to:
this.eventAggregator.publish('MyrowData', item);
This will work because you've already provided item in your function call click.delegate="PopulateData(item, $event)".
In fact, you could even delete $event and event from the two PopulateData definitions (in data-form.js and data-form.html).
When I implement these suggestions, your data is also validated correctly.

Yii2 Gridview get all selected row for all pagination

I wrapped my gridview with Pjax widget like this
\yii\widgets\Pjax::begin();
gridview
\yii\widgets\Pjax::end();
in order to make the gridview make ajax request when I click on each pagination.
I also use ['class' => 'yii\grid\CheckboxColumn'], in column as well.
and I find that when I'm on first pagination I checked some rows and then go to second page and check some rows but when I go back to first page what I've checked is gone.
My question is how can I keep all checkedrow for all pagination
With current conditions (Pjax, multiple pages, yii\grid\CheckboxColumn) it's impossible because of the way it works.
When you click on the pagination links all GridView html content is replaced by new one that comes from the AJAX response.
So obviously all selected checkboxes on the previous page are gone.
Few possible ways to solve that:
1) Write custom javascript and server side logic.
As one of the options, you can send AJAX request to server with parameter meaning that user has chosen to select all data for the bulk delete operation (or use separate controller action for bulk deletion). In this case actually we don't need to get the selected data from user, because we can simply get them from database (credits - Seng).
2) Increase number of displayed rows per page.
3) Use infinite scroll extension, for example this.
4) Break desired action in several iterations:
select needed rows on first page, do action (for example, delete).
repeat this again for other pages.
You can get selected rows like that:
$('#your-grid-view').yiiGridView('getSelectedRows');
[infinite scroll] : http://kop.github.io/yii2-scroll-pager/ will work good if you do not have any pjax filters. If you have filters also in play, do not use this plugin as it does not support pjax filters with it. For rest of the applications it is perfect to use.
Update1 : it seems to be straight forward than expected, here is the how I accomplished it
Add following lines to the checkbox column
'checkboxOptions' => function($data){
return ['id' => $data->id, 'onClick' => 'selectedRow(this)'];
}
Now add following JS to the common js file you will have in your project of the page where this datagrid resides
var selectedItems=[]; //global variable
/**
* Store the value of the selected row or delete it if it is unselected
*
* #param {checkbox} ele
*/
function selectedRow(ele){
if($(ele).is(':checked')) {
//push the element
if(!selectedItems.includes($(ele).attr('id'))) {
selectedItems.push($(ele).attr('id'));
}
} else {
//pop the element
if(selectedItems.includes($(ele).attr('id'))) {
selectedItems.pop($(ele).attr('id'));
}
}
}
Above function will store the selected row ids in the global variable array
Now add following lines to pjax:end event handler
$(document).on('pjax:end', function () {
//Select the already selected items on the grid view
if(!empty(selectedItems)){
$.each(selectedItems, function (index,value) {
$("#"+value).attr('checked',true);
});
}
});
Hope it helps.
I just solved this problem and it works properly with Pjax.
You may use my CheckboxColumn. I hope this can help. The checked items are recorded with cookies.
You can read the part with //add by hezll to understand how to fix it, because I didn't provide a complete general one.
Hope it works for you.
https://owncloud.xiwangkt.com/index.php/s/dGH3fezC5MGCx4H

Ng-grid with external data and TypeScript: compile error "Cannot set property 'gridDim' of undefined"

Update #1: after the fix I commented about, now my app starts but the grid is not rendered except for its bounding box and filter button and popup. Yet, I get no error from the console, and as far as I can arrive with the debugger, I can see that data got from the server are OK. If I use Batarang, I can see the scope corresponding to my model, correctly filled with items. I updated the downloadable repro solution accordingly. Could anyone explain why ng-grid is not updating here?
I'm starting to play with ng-grid and TypeScript and I'm finding issues as soon as my test app starts up. See the bottom of this post for a link to a full test solution. Surely I have made tons of errors even in these few files, but I'd like to have something to start with and learn more step by step.
The MVC app has two client-side applications:
app.js for the default view (Home/Index). No typescript here, and the whole code is self-contained in this single file. The code is derived from the paging example in the ng-grid documentation and tries to stay as simplest as possible.
MyApp.js for the more realistic sample in another view (Home/Model). This sample uses services, models and controllers and its JS code is compiled from TypeScript. To keep things simple, I'm just storing these components under Scripts/App, in folders for Controllers, Models and Services, and each file contains just a single class or interface. The generated JS files are manually included in the view.
app.js works, except that it has issues with filtering. I posted about these here:
Server-side filtering with ng-grid: binding issue?
MyApp.js has startup issues with ng-grid. As soon as the app starts, a TypeError is thrown in the grid binding:
TypeError: Cannot set property 'gridDim' of undefined
at ngGridDirectives.directive.ngGridDirective.compile.pre (http://localhost:55203/Scripts/ng-grid-2.0.7.js:2708:37)
at nodeLinkFn (http://localhost:55203/Scripts/angular.js:4392:13)
at compositeLinkFn (http://localhost:55203/Scripts/angular.js:4015:15)
at nodeLinkFn (http://localhost:55203/Scripts/angular.js:4400:24)
at compositeLinkFn (http://localhost:55203/Scripts/angular.js:4015:15)
at publicLinkFn (http://localhost:55203/Scripts/angular.js:3920:30)
at resumeBootstrapInternal (http://localhost:55203/Scripts/angular.js:983:27)
at Object.$get.Scope.$eval (http://localhost:55203/Scripts/angular.js:8057:28)
at Object.$get.Scope.$apply (http://localhost:55203/Scripts/angular.js:8137:23)
at resumeBootstrapInternal (http://localhost:55203/Scripts/angular.js:981:15) <div ng-grid="gridOptions" style="height: 400px" class="ng-scope"> angular.js:5754
The only similar issue I found by googling is https://github.com/angular-ui/ng-grid/issues/60, but it does not seem to be related to my case as there the grid options were setup too late.
The server side just has an API RESTful controller returning server-paged, sorted and filtered items.
You can find the full repro solution here (just save, unzip and open; all the dependencies come from NuGet); see the readme.txt file for more information:
http://sdrv.ms/167gv0F
Just start the app and click MODEL in the upper right corner to run the TypeScript app throwing the error. The whole app is composed of 1 controller, 1 service and 1 model.
For starters like me, it would be nice to have a simple working example like this one. Could anyone help?
This error means gridOptions has not yet been defined by the time that Angular attempts to parse ng-grid="yourArray", where yourArray is the same array supplied to gridOptions. I had the same problem after refactoring a previously working ng-grid.
So gridOptions must be defined before the element which has ng-grid="yourArray" attribute applied to it (rather than within that element's own controller).
I resolved this by defining gridOptions in an outer element somewhere (on global/app scope, for instance).
P.S. Maybe there is a better way, but this has worked for me.
Where you are adding data to your grid?
If you are writing $scope.myGrid={data:"someObj"}; in a success call then it won't work.
See the below reason:(which is listed in https://github.com/angular-ui/ng-grid/issues/60)
You can't define the grid options in the success call. You need to define
them on the scope in your controller and then set the data or column
definitions, etc... from the success call.
What you have to do?, First is to see how this made ​​your project and revizar if your queries or data access, the beams through a service, if so this I must add the file that manages routes app, the client side.
remain so.
'use strict';
angular.module('iseApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute',
**'ngGrid',**
'campaignServices',
'dialinglistServices',
'itemServices'
])
.config(function ($routeProvider, $locationProvider, $httpProvider) {
$routeProvider
As you are adding your ng-grid in a directive, you have to make sure the grid options are loaded before it tries to parse your html.
You could set a boolean in your link function :
scope.isDirectiveLoaded=true;
And then, in your template, use a ng-if :
<div ng-if="isDirectiveLoaded">
<div ng-grid="myGrid"/>
</div>
I got to the same issue, empty grid was rendered.
The way I got to it in the end was to setup my this.gridOptions in the constructor of the controller, within the component. In the options everything is referenced with $ctrl like this. So the data references $ctrl.gridData. gridData is specified as a property in my component controller. $ctrl is not defined as a property.
This was done in the constructor before the data was loaded. this.gridData was defined after in the constructor and then populated later in another function. The options were defined first, I think this is important from some things I read.
For the event hooks pass null instead of $scope.
this.gridOptions = {
enableGridMenu: true,
minRowsToShow: 25,
rowHeight: 36,
enableRowHashing: true,
data: '$ctrl.gridData',
rowTemplate: this.$rootScope.blockedRowTemplate,
onRegisterApi: ($ctrl) => {
this.gridApi = $ctrl;
this.gridApi.colMovable.on.columnPositionChanged(null, (colDef, originalPosition, newPosition) => {
this.saveState();
});
this.gridApi.colResizable.on.columnSizeChanged(null, (colDef, deltaChange) => {
this.saveState();
});
this.gridApi.core.on.columnVisibilityChanged(null, (column) => {
this.saveState();
});
this.gridApi.core.on.sortChanged(null, (grid, sortColumns) => {
this.saveState();
});
this.gridApi.core.on.filterChanged(null, (grid, sortColumns) => {
this.saveState();
});
}
};
In the row template I was referencing functions defined in my component. Before conversion to a component I referenced functions like this:
ng-click="grid.appScope.jumpToExport(row.entity);"
After conversion to the component I needed to add the $ctrl before the function name like this
ng-click="grid.appScope.$ctrl.jumpToExport(row.entity);"
And this is how the component is referenced in the html
<div ui-grid="$ctrl.gridOptions" ng-if="$ctrl.gridData.length != undefined && $ctrl.gridData.length > 0" class="data-grid" ui-grid-save-state ui-grid-resize-columns ui-grid-move-columns></div>

Dojo dnd (drag and drop) 1.7.2 - How to maintain a separate (non-dojo-dnd) list?

I'm using Dojo dnd version 1.7.2 and it's generally working really well. I'm happy.
My app maintains many arrays of items, and as the user drags and drops items around, I need to ensure that my arrays are updated to reflect the contents the user is seeing.
In order to accomplish this, I think I need to run some code around the time of Source.onDndDrop
If I use dojo.connect to set up a handler on my Source for onDndDrop or onDrop, my code seems to get called too late. That is, the source that's passed to the handler doesn't actually have the item in it any more.
This is a problem because I want to call source.getItem(nodes[0].id) to get at the actual data that's being dragged around so I can find it in my arrays and update those arrays to reflect the change the user is making.
Perhaps I'm going about this wrong; and there's a better way?
Ok, I found a good way to do this. A hint was found in this answer to a different question:
https://stackoverflow.com/a/1635554/573110
My successful sequence of calls is basically:
var source = new dojo.dnd.Source( element, creationParams );
var dropHandler = function(source,nodes,copy){
var o = source.getItem(nodes[0].id); // 0 is cool here because singular:true.
// party on o.data ...
this.oldDrop(source,nodes,copy);
}
source.oldDrop = source.onDrop;
source.onDrop = dropHandler;
This ensures that the new implementation of onDrop (dropHandler) is called right before the previously installed one.
Kind'a shooting a blank i guess, there are a few different implementations of the dndSource. But there are a some things one needs to know about the events / checkfunctions that are called during the mouseover / dnddrop.
One approach would be to setup checkAcceptance(source, nodes) for any target you may have. Then keep a reference of the nodes currently dragged. Gets tricky though, with multiple containers that has dynamic contents.
Setup your Source, whilst overriding the checkAcceptance and use a known, (perhaps global) variable to keep track.
var lastReference = null;
var target = dojo.dnd.Source(node, {
checkAcceptance(source, nodes) : function() {
// this is called when 'nodes' are attempted dropped - on mouseover
lastReference = source.getItem(nodes[0].id)
// returning boolean here will either green-light or deny your drop
// use fallback (default) behavior like so:
return this.inhertied(arguments);
}
});
Best approach might just be like this - you get both target and source plus nodes at hand, however you need to find out which is the right stack to look for the node in. I believe it is published at same time as the event (onDrop) youre allready using:
dojo.subscribe("/dnd/drop", function(source, nodes, copy, target) {
// figure out your source container id and target dropzone id
// do stuff with nodes
var itemId = nodes[0].id
}
Available mechanics/topics through dojo.subscribe and events are listed here
http://dojotoolkit.org/reference-guide/1.7/dojo/dnd.html#manager