I am trying to link up the value of a dijit.form.Select to a ListController. I have it working with FilteringSelects and TextBoxes, but it won't work with regular Selects.
I am writing an editor for a list of records. I am using the ListController to represent the list of records, and I want all my widgets to be able to edit the "current record". Each widget, therefore, binds to a different property in the ListController. Then I will be able to switch between the different records, but use the same widgets to edit them.
The controller of course has an idea of which record is the current one, and some of the widgets work. So when I edit, say, the Barcode field with a TextBox widget, the ListController sets the value on the correct record.
However I haven't been able to hook up the Select widget's value to its intended property in the ListController.
I have tried putting the value: mvc.at( controller, 'field' ) in the constructor as well setting it directly after the call, but no dice. Any ideas?
require( [ 'dijit/form/Select', ], function( Select ) {
var testSelect = new Select( {
value: mvc.at( controller, 'field' ), // controller is a ListController
store: store,
searchAttr: "description",
labelAttr: "description"
}, 'TestSelect' );
} );
require( [ 'dijit/form/Select', ], function( Select ) {
var testSelect = new Select( {
store: store,
searchAttr: "description",
labelAttr: "description"
}, 'TestSelect' );
testSelect.set( 'value', mvc.at( controller, 'field' ) );
} );
How does mvc.at() actually work? It doesn't seem to set the value property to an mvc.at value, even on the widgets that do work. There seems to be some winking and nudging going on inside the widget code. Something about _refs?
A dijit/form/Select value is expecting a single value, but a ListController holds an array so you can not directly bind a field in a ListController to a Select's value. You could place the Select inside of a dojox/mvc/Group which has something like this:
data-dojo-props="target: at(controller,'cursor')"
And then you would setup your select with something like this:
value: mvc.at( 'rel:', 'field' ),
And anytime the cursor or cursorIndex is changed on the Controller the select would be updated.
If you want to set the value directly from the controller, I think you would have to do something like this:
value: mvc.at( controller.model[0], 'field' ),
Related
I had setup datatables to display a users, each user has more images.
Datatables column that displays the images is like this:
{data: 'images', render: function ( data, type, row ) {
var out='';
if (type === 'display') {
row.images.forEach(function(item){
out+=''+item.file_name+' ';
});}
if (type === 'search') {
row.images.forEach(function(item){
out+=item.file_name+' ';
});}
return out;}
},
All other fields come to the datatables as key:value, while images comes for each user as an array of objects.
All Image File names are displayed correctly in datatables, and links works good also, however general search does not work
I want general search to work with or without search for image file name.
I also specified searchable: false, but still search didn't work, like this:
{data: 'images', render: function ( data, type, row ) {..},searchable: false}
Search works ok without image column!
Any ideas?
I followed the Implementing an inline widget tutorial at https://ckeditor.com/docs/ckeditor5/latest/framework/guides/tutorials/implementing-an-inline-widget.html.
I want to extend it to enable bolding of placeholders.
I added this.editor.model.schema.extend( 'placeholder', { allowAttributes: 'bold' } ); to PlaceholderEditing.init(), so it now looks like this:
init() {
this._defineSchema();
this._defineConverters();
this.editor.commands.add('placeholder', new PlaceholderCommand(this.editor));
this.editor.editing.mapper.on(
'viewToModelPosition',
viewToModelPositionOutsideModelElement(this.editor.model, viewElement => viewElement.hasClass('placeholder'))
);
this.editor.config.define( 'placeholderConfig', {
types: [ 'date', 'first name', 'surname' ]
} );
this.editor.model.schema.extend( 'placeholder', { allowAttributes: 'bold' } ); //ADDED
}
Then I wrapped my placeholder in <strong></strong>, like so:
<strong><span class="placeholder" >{mike}</span></strong>
The inspector shows me the attribute gets added to placeholder in the model, like so:
But, the rendered html in the editor does not have <strong></strong> downcast on it
How can I make this work?
It seems there is no way to do this cleanly currently. There is already an issue for it: https://github.com/ckeditor/ckeditor5/issues/1633
I see in CKEitor 4.5 there is a new drag and drop system. I would like to drop external DIVs or SPANs into my CkEditor and have them turn into "placeholders" "fake objects" or "protected source" objects. I.e., the dropped object should turn into arbitrary HTML that's related to the content.
The available demos seem to be about uploading content, but this is different and I'd appreciate a demo ...
Yes, it is possible. CKEditor 4.5 is in the beta phase at the moment, what means there is no tutorials yet, but here is sample how to do it.
First, you need to mark your data on dragstart. You can simple set text:
dragstart( evt ) {
evt.dataTransfer.setData( 'text', 'foo' );
} );
But then you need to make your text unique, otherwise every time someone drop foo it will be recognize as your container.
I prefer to use CKEditor data transfer facade, which let you use custom data type on every browser (including IE 8+):
dragstart( evt ) {
var evt = { data: { $: $evt } }; // Create CKEditor event.
CKEDITOR.plugins.clipboard.initDragDataTransfer( evt );
evt.data.dataTransfer.setData( 'mydatatype', true );
// Some text need to be set, otherwise drop event will not be fired.
evt.data.dataTransfer.setData( 'text', 'x' );
} );
Then in the CKEDITOR you can recognize this data and set your html to be dropped. You can replace dropped content whit whatever you need. Simple set text/html data in the drop event:
editor.on( 'drop', function( evt ) {
var dataTransfer = evt.data.dataTransfer;
if ( dataTransfer.getData( 'mydatatype' ) ) {
dataTransfer.setData( 'text/html', '<div>Bar</div>' );
}
} );
You can find working sample here: http://jsfiddle.net/oqzy8dog/3/
Some of my columns are not editable but I want all of the columns to display in the add form.
I was thinking that I can use the "beforeShowForm" event and call a javascript function that will dynamically change the column attribute back to editable so they will show up in the add form.
The typical approach for this is to make fields generally editable and hide them in edit dialog.
You can hide/show fields by looking for table rows which ids are being built like this:
tr_ColumnName
So in case you would have UserName column the id would be like this:
tr_UserName
Assuming you are using jQuery, you can wire-up this to your Lib.Web.Mvc configuration like this:
.Navigator(new Lib.Web.Mvc.JQuery.JqGrid.JqGridNavigatorOptions() { ... },
editActionOptions: new Lib.Web.Mvc.JQuery.JqGrid.JqGridNavigatorEditActionOptions()
{
...
BeforeShowForm : "function(form) { $('#tr_UserName', form).hide(); }"
},
addActionOptions: new Lib.Web.Mvc.JQuery.JqGrid.JqGridNavigatorEditActionOptions()
{
...
BeforeShowForm : "function(form) { $('#tr_UserName', form).show(); }"
}
);
I figured how to use the event beforeShowForm.
Note: I have a using statement at the top of the view, so do not need to use the full namespace
#using Lib.Web.Mvc.JQuery.JqGrid
Here is an example within the Navigator form:
.Navigator(new JqGrid.JqGridNavigatorOptions()
{ Add = true, Edit = false, Delete = false, Search = false },
null,
addActionOptions: new JqGridNavigatorEditActionOptions()
{
Url = Url.Action("Add"),
BeforeShowForm = "function () {$('#bob').jqGrid('setColProp',
'Place', {editable:true})
})
I have a combobox in a view that is tied to a data store / model that uses Ext.Direct to load the data for the drop down.
In my controller where I open the view that contains the combobox, I kick off the load of the store.
This all works, but when I click on the combobox, it kicks off another load (masks the screen with loading) and re-loads the store. I need to prevent that second load since it's already loading.
Store:
Ext.define('ESDB.store.Employees', {
extend: 'Ext.data.Store',
model: 'ESDB.model.Employee',
autoLoad:false,
proxy: {
type: 'direct',
api: {
create : undefined,
read : EmployeeService.getRecords,
update : EmployeeService.setRecord,
destroy : undefined
}
}
});
Model:
Ext.define('ESDB.model.Employee', {
extend: 'Ext.data.Model',
fields: ['id','name','login','pw','domain','lastLogin','addedDate','active','ulevel','staffID']
});
View:
(relevant part - the combo box - there are no other references to the store or model in the view)
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'combobox',
name : 'callTakenBy',
fieldLabel: 'Taken By',
displayField: 'name',
queryMode: 'remote',
valueField: 'id',
store: "Employees",
editable: false
}
]]}
Controller (when they double click a row in the grid, it kicks off the load for the employees store, then opens the view):
encounterRowClicked: function(grid, record) {
console.log('Double clicked on ' + record.get('id'));
var store = this.getEmployeesStore();
store.load({
params: {
},
callback: function(r,options,success) { } //callback
}); //store.load
// load the view:
var view = Ext.widget('encounteredit');
view.down('form').loadRecord(record);
}
All this code works, but when I get in to the view, where the combobox is properly displaying one of the loaded values, I click on the combobox and it kicks off another load of the store. It works, but then I have to click again to actually choose a different value. So I am looking for a way to tell the combobox to simply use the store, not to load it-- seems like it should already know that it's loaded and to simply use it?
You need to set the queryMode : 'local' for the combobox. As you can see in the docs, the default value is remote (by the way you should remove the mode: 'remote', mode is not a valid config for the combobox).
In queryMode: 'remote', the ComboBox loads its Store dynamically based upon user interaction.
You should use 'local' because you already have the data localy in the store