How do I use JQuery Datepicker with Backbone-Forms? - backbone.js

var User = Backbone.Model.extend({
schema: {
date: {type: 'Date'}
}
});
var user = new User();
var form = new Backbone.Form({
model: user
}).render();
$('.bootstrap').append(form.el);
What type do I enter to use the included JQuery-UI datepicker? There is no documentation on this other than:
The old jQuery editors are still included but may be moved to another repository:
jqueryui.List
jqueryui.Date (uses the jQuery UI popup datepicker)
jqueryui.DateTime
The schema type is declared in quotes and I can't figure out what the string for jqueryui.Date would be - and that doesn't work for sure.

You want to create a custom editor that you'll name for example: 'DatePicker'.
All the editors are attached to Backbone.Form.editors. Because the DatePicker is rendered exactly like a text field, we can use the text field as a base and only override the behavior specific to the datepicker.
I often use moment.js for some date related work, so this example also includes this. Also it's based on Bootstrap DatePicker and not the jQuery one, but this would be almost 100% the same.
Backbone.Form.editors.DatePicker = Backbone.Form.editors.Text.extend({
render: function() {
// Call the parent's render method
Backbone.Form.editors.Text.prototype.render.call(this);
// Then make the editor's element a datepicker.
this.$el.datepicker({
format: 'yyyy-mm-dd',
autoclose: true,
weekStart: 1
});
return this;
},
// The set value must correctl
setValue: function(value) {
this.$el.val(moment(value).format('YYYY-MM-DD'));
}
});
That's it, you can now use your date picker like this:
schema: {
birthday: { title: 'When were you born', type: 'DatePicker'}
}

Not sure it undestanding right your Question
but I think you can atach the Jquery date pickers in the initialize method of the view

Related

How to add 3rd party editor to Wagtail 2.2+?

We have been using Froala editor within Wagtail for years, and even though Draftail is nice, the end user wants to continue to use Frola, especially as a license fee has been paid for it, and it offers extra functionality that they use.
I have used the following which works great for any version of Wagtail prior to version 2.2:
https://github.com/jaydensmith/wagtailfroala/pull/5/commits/d64d00831375489cfacefa7af697a9e76fb7f175
However in Wagtail version 2.2 this has changed:
https://docs.wagtail.org/en/stable/releases/2.2.html#javascript-templates-in-modal-workflows-are-deprecated, this causes selecting images within Froala to no longer work correctly. You get to pick the image, but it fails to move onto the 2nd dialog to select alignment and then click insert.
It looks like wagtailfroala/static/froala/js/froala.js needs to be changed to add onload to the ModalWorkflow.
$.FE.RegisterCommand('insertImage', {
title: 'Insert Image',
undo: false,
focus: true,
refreshAfterCallback: false,
popup: true,
callback: function () {
var editor = this;
return ModalWorkflow({
url: window.chooserUrls.imageChooser + '?select_format=true',
responses: {
imageChosen: function(imageData) {
editor.edit.off();
var $img = $(imageData.html);
$img.on('load', function() {
_loadedCallback(editor, $(this));
});
// Make sure we have focus.
// Call the event.
editor.edit.on();
editor.events.focus(true);
editor.selection.restore();
editor.undo.saveStep();
// Insert marker and then replace it with the image.
if (editor.opts.imageSplitHTML) {
editor.markers.split();
} else {
editor.markers.insert();
}
var $marker = editor.$el.find('.fr-marker');
$marker.replaceWith($img);
editor.html.wrap();
editor.selection.clear();
editor.events.trigger('contentChanged');
editor.undo.saveStep();
editor.events.trigger('image.inserted', [$img]);
}
}
});
},
plugin: 'image'
});
But what needs to be added to make it work? I can't find any documentation or examples on how do to this? Please help or point me in the direction of the documentation for how this should be done.
Thank you so much in advance.

How to prevent Kendo MultiSelect from losing values after editing in a grid template?

I have a grid that displays a comma-separated list of values, and it has an array that gets used in a template editor for the grid. (On the server, I transform the comma-separated list to an array for the Kendo multiselect AngularJS directive). I have almost everything working: display, edit, and adding values in the multiselect.
There's just one weird thing happening: after I add a value in the multiselect, click Save in the editor, and reopen the editor, the multiselect then only displays one of the most-recently entered values. I know that the values are there and going through the pipeline, because the values make it into the database. I can refresh the page, open the editor, and all the values display in the multiselect correctly, including the one I just added.
It's as if kendo "forgets" most of the values when I reopen the editor. How can this be prevented? Does the MultiSelect need to be rebound to the values? If so, how?
I have tried adding this onChange event, but it had no effect. I've added valuePrimitive to no effect. I tried specifying k-rebind, but it caused an error.
Here's the directive being used in the text/x-kendo-template:
<select kendo-multi-select
id="zipCode"
k-placeholder="'Enter zip codes...'"
style="width: 225px"
k-on-change="dataItem.dirty=true"
k-auto-bind="false"
k-min-length="3"
k-enforce-min-length="true"
k-data-source="options.zipCodeDataSource"
k-data-text-field="'text'"
k-filter="'startsWith'"
k-filtering="options.zipCodeFiltering"
k-no-data-template="'...'"
k-ng-model="dataItem.zipArray"
k-highlight-first="true" />
And this is the DataSource:
options.zipCodeDataSource = new kendo.data.DataSource({
severFiltering: true,
transport: {
read: {
url: serviceUrl + "ZipCode/Get",
type: "GET",
dataType: "json",
contentType: jsonType,
data: function (e) {
// get your widget.
let widget = $('#zipCode').data('kendoMultiSelect');
// get the text input
let filter = widget.input.val();
// what you return here will be in the query string
return {
filter: filter
};
}
},
},
schema: {
data: "data",
total: "Count",
model:
{
id: "text",
fields: {
text: { editable: false, defaultValue: 0 },
}
},
parse: function (response) {
return response;
}
},
error: function (e) {
}
});
If I display {{dataItem.zipArray}} in a <pre> all of the expected values are there.
I wonder if something needs to be added to the edit event handler in the kendo grid definition, but I'm not sure what it would be. I've had to do binding like that for the dropdownlist directive.
edit: function (e) {
if (e.model.marketId === 0) {
e.container.kendoWindow("title", "Add");
} else {
e.container.kendoWindow("title", "Edit");
}
// re-bind multi-select here??
// These two lines actually cause the multiselect to lose pre-existing items in dataItem.zipArray
// var multiselect = kendo.widgetInstance(angular.element('#zipCode'));
// multiselect.trigger('change');
}
...
Update:
This dojo demonstrates the issue.
Run the dojo
Edit the first record in the Contracts grid
Add a zip code such as 22250
Click Save
Then click Edit on the first row again
Only zip code 22250 is displayed in the editor
Also, I notice that if I change k-min-length="3" to k-min-length="1", then the issue goes away. But in the scenario I'm working on, it needs to be 3.
This seems to be an issue with kendo itself. Back then this issue was reported here.
Ok based on the reply from telerik, this issue has been fixed in 2017 R3 SP1 release (2017.3.1018). You can verify it by using this updated dojo example:
http://dojo.telerik.com/IREVAXar/3

Applying an angular filter to a formly field

Is there an ability to set angular filters to formly fields? I've tried adding a "filter: 'uppercase'" to the templateOptions object, but to no avail, the input field remains lowercase.
And, if so, is adding parameters just as simple as "'myfilter:param1:param2'"?
Thanks in advance
You could do it, but to make it work like that, you would need to make it an HTML template.
The easiest way would be to create a service and just set flags in the templateOptions that would determine if those functions get called and then return the values from expressionProperties that check the flags values.
For instance:
{
key: 'Upper',
templateOptions: {
label: 'Name to Upper',
upper: true
}
},
expressionProperties: {
'templateOptions.upper': function($viewValue, $modelValue, $scope) {
if($scope.to.upper) $viewValue = ....//CALL UPPER CASE FUNCTION
return $viewValue;
}
}
Alternatively, if this is a one time thing, you could simply do $viewValue = $viewValue.toUpperCase();

Need to set class/id values on buttons in Extjs MessageBox

Our testing team require IDs or class values to be set on the HTML elements in our message popup boxes. This is for their automated tests.
I can pass in a class value for the dialog panel by passing in a cls value like so:
Ext.Msg.show({
title:'Reset Grid Layout',
msg: 'Are you sure that you want to reset the grid layout?',
cls:'Reset-Grid-Layout-Message',
buttons: Ext.Msg.YESNO,
fn: function (response) {
if (response == 'yes') {
}
},
icon: Ext.window.MessageBox.QUESTION
});
Now we also need it on the buttons, and also on the text being displayed. Is there some way of getting a cls value onto the buttons?
I was thinking it may be possible to expand the button parameter into something like :
buttons : [{name:'but1', cls:'asdf'}, {name:'but2', cls:'asdf2'}]
But google is not giving me back anything useful.
If your testing team uses Selenium for their automated test, adding ids/classes in every component could be difficult for both of you.
Overriding components in Ext is a good solution, but I don't recommend this because it will affect all your components. Unless you know what you're doing.
I suggest, extend Ext.window.MessageBox and generate classes for your buttons based on your parent cls.
// Put this somewhere like /custom/messagebox.js
Ext.define('App.MyMessageBox', {
extend: 'Ext.window.MessageBox'
,initConfig: function(config) {
this.callParent(arguments);
}
,makeButton: function(btnIdx) {
var me = this;
var btnId = me.buttonIds[btnIdx];
return new Ext.button.Button({
handler: me.btnCallback
,cls: me.cls + '-' + btnId
,itemId: btnId
,scope: me
,text: me.buttonText[btnId]
,minWidth: 75
});
}
});
To use:
App.Box = new App.MyMessageBox({
cls:'reset-grid-layout'
}).show({
title:'Reset Grid Layout'
,msg: 'Are you sure that you want to reset the grid layout?'
,buttons: Ext.Msg.YESNO
,icon: Ext.window.MessageBox.QUESTION
});
Your buttons will have reset-grid-layout-yes and reset-grid-layout-no class.
You can do the same with other components you have. Check out the Fiddle. https://fiddle.sencha.com/#fiddle/7qb
You should refer to the API
cls : String A CSS class string to apply to the button's main element.
Overrides: Ext.AbstractComponent.cls
You can also use the filter on right side (not the one in the right top corner). Just type cls and you will see all properties, methods and events containing cls (note that you see by default just public members, use the menu on the right of this searchfield to extend this)
Edit
If you just need it for testing purpose I would recommend to override the responsible method. This should work (untested!)
Ext.window.MessageBox.override({
buttonClasses: [
'okCls', 'yesCls', 'noCls', 'cancelCls'
],
makeButton: function(btnIdx) {
var btnId = this.buttonIds[btnIdx];
var btnCls = this.buttonClasses[btnIdx];
return new Ext.button.Button({
handler: this.btnCallback,
cls: btnCls,
itemId: btnId,
scope: this,
text: this.buttonText[btnId],
minWidth: 75
});
}
});

show dynamic data using checkbox in extjs

I have a combo box in which the user selects a value, that value is passed to the checkbox data store and it is populated dynamically from database (oracle). I tried the code below. It seems that the selected parameter is being passed to checkbox and I can see the data being populated on the console. I just can't render the checkbox on form. The error I get is: typeError: this.items[0] is undefined.
testArray = new Array();
var testStore = new Ext.data.JsonStore({
proxy:new Ext.data.HttpProxy({
method:'GET',
prettyUrls:false,
url:'kiu.htm',
listeners:{
'loadexception':{
fn:test.form.data.loadException
}
}
}),
fields:["id", "display"],
reader:new Ext.data.JsonReader({
id:'id',
root:'results',
totalProperty:'totalCount',
fields:new Ext.data.Record.create([
{name:'id',type:'int'},
{name:'display',type:'string'}
])
}),
listeners:{
load: function(t, records, options, success) {
for(var i=0; i<records.length; i++) {
testArray.push({name:records[i].data.id, boxLabel: records[i].data.display});
alert(testArray[i].id);
}
}
}
});
{
xtype:'combo',
id:'comboid3',
store:combostore,
displayField:'display',
valueField:'id',
tabIndex:1,
loadingText:'Loading combo...',
listeners :{
select:function(event){
testStore.baseParams = {
"comboid":Ext.getCmp('comboid3').getValue()
};
testStore.load();
}
}
},
{
xtype:'checkboxgroup',
fieldLabel:'Check',
items:testArray
}
Help will be appreciated!
Specifying the Ext JS version is always going to be helpful. It appears this must be 2.x or 3.x and not the current version.
The issue is timing, load calls are asynchronous so by attempting to utilize testArray in this fashion you are likely referencing an empty array by the time it parses the items property of your checkboxgroup. You have a couple options around this... one is to grab a reference to the checkbox group and add the items into it, the other is to not put the checkbox group in the form at all until the call returns and then add it with the populated items array. In either case it is likely that you will need to look up a component reference to either the FormPanel or the CheckboxGroup from within the load handler function and call the 'add' method to add child items.

Resources