Enyo custom properties - javascript

I try to create my own kind in enyo
enyo.kind(
{
name: "DeviceButton",
kind: "Button",
caption: "",
published: { userAgent: "" },
flex: 1,
onclick: "butclick",
butclick: function() { console.log("User agent changed to " + this.userAgent) }
})
But when I click there is nothing shown
If I just did
onclick: console.log("User agent changed to " + this.userAgent)
It was printed that this.userAgent is undefined
What am I doing wrong?
Btw., is it possible to send parameters via onclick (so that the function repsponding to the click get a variable)
Thanks

The problem you're having here is that the onclick property is actually giving the name of the event handler for the Enyo to send the event to when the click is received. The "butclick" event isn't dispatched to the DeviceButton, but rather to its parent.
If you want to handle the event entirely within your kind, then you need to set it up as a "handler". In Enyo 2.x, you do it like this:
enyo.kind(
{
name: "DeviceButton",
kind: "Button",
caption: "",
published: { userAgent: "" },
flex: 1,
handlers {
onclick: "butclick"
},
butclick: function() { console.log("User agent changed to " + this.userAgent) }
})
In Enyo 1.x, you'd just need to name the handler function "onclickHandler". I mention the Enyo 1 solution because I see that you have "flex: 1" in your definition. Flexbox isn't supported in Enyo 2, we have a "Fittable" system instead.

I made a little example for you how enyo can handle sending and receiving values to and from a custom kind. I also added some short comments inside the code.
http://jsfiddle.net/joopmicroop/K3azX/
enyo.kind({
name: 'App',
kind: enyo.Control,
components: [
{kind:'FittableRows', components:[
// calls the custom kind by it's default values
{kind:'DeviceButton',name:'bttn1', classes:'joop-btn',ontap:'printToTarget'},
// calls the custom kind and pass the variables to the DeviceButton kind
{kind:'DeviceButton', name:'bttn2', btnstring:'Get Agent', useragent:'chrome', classes:'joop-btn', ontap:'printToTarget'},
{tag:'div', name:'targetContainer', content:'no button clicked yet', classes:'joop-target'},
]},
],
printToTarget:function(inSender, inEvent){
// inSender = the button that was pressed
this.$.targetContainer.setContent(inSender.name+' has used the value: "'+inSender.getUseragent()+'" and sends the value of: "'+inSender.getValueToPrint()+'" back.');
},
});
enyo.kind({
name:'DeviceButton',
kind:enyo.Control,
components:[
{kind:'onyx.Button',name:'btn', ontap:'printUsrAgent'}
],
published:{
btnstring:'default btnstring', // value that will be received
useragent:'default useragent', // value that will be received
valueToPrint:'default valueToPrint' // value that will be used
},
rendered:function(){
this.inherited(arguments);
this.$.btn.setContent(this.btnstring);
},
printUsrAgent:function(inSender,inEvent){
// set a parameter with the value that was received of if not received use the default value (normaly would do some calculations with it first)
this.valueToPrint = this.useragent+' after changes';
},
});
​

Related

How to deny the drop event?

Before version 2016.3.914, it was possible to cancel a drop event by calling e.setStatusClass("k-denied");
$("#treeview").kendoTreeView({
dragAndDrop: true,
dataSource: [
{ text: "foo", items: [
{ text: "bar" }
] }
],
drag: function(e) {
e.setStatusClass("k-denied");
}
});
However, starting from version 2016.3.914, the pre-defined status classe k-denied doesn't work anymore. The documentation says that k-i- should be added as class prefix but k-i-denied doesn't work as the cancel icon doesn't appear and the drop is still allowed.
Please note that from version 2016.3.914 the naming convention for pre-defined status classes is k-i-className.
Note that status classes are returned without the k- prefix by
e.statusClass, but this prefix is required when setting a predefined
status class via e.setStatusClass. A prefix is not required if setting
a custom status CSS class.
The documentation was right about one thing. We do have to use the k-i- prefix. However, what the documentation doesn't tell you is the fact that kendo has changed the pre-defined status classes from k-denied to k-i-cancel
$("#treeview").kendoTreeView({
dragAndDrop: true,
dataSource: [
{ text: "foo", items: [
{ text: "bar" }
] }
],
drag: function(e) {
e.setStatusClass("k-i-cancel");
}
});

Refresh data in table after creating a record

In my Ui5 app I have added CREATE operation using oData. But when i am trying to create entry it is getting added in backend but in table it is showing NO DATA (refer image 1). but when I refresh the same page it is there (refer image 2). With single entry ,it is automatically getting refreshed 
problem is with Multiple entries.
Please refer the screenshot and code for clear view.
After Clicking CREATE button:
After Refreshing WebPage:
onCreate: function() {
var oModel = this.getView().getModel();
var contactEntry1 = {
ProductID: 'KT-1960',
TypeCode: 'AD',
SupplierID: '0100000001',
TaxTarifCode: 1,
Category: 'Notebooks',
MeasureUnit: 'EA',
CurrencyCode: 'EUR',
Name: 'Urvish',
Description: 'First batch entry',
},
contactEntry2 = {
ProductID: 'KT-1982',
TypeCode: 'AD',
SupplierID: '0100000001',
TaxTarifCode: 1,
Category: 'Notebooks',
MeasureUnit: 'EA',
CurrencyCode: 'EUR',
Name: 'Urvish',
Description: 'Second batch entry',
};
oModel.setUseBatch(true);
oModel.create('/ProductSet', contactEntry1);
oModel.create('/ProductSet', contactEntry2);
oModel.refresh(true);
},
Looks like that you use the asynchronous operation for create but think that they are synchronous.
In order to fix this out, you can send these 2 create in one $batch request, but use the createEntry method of ODataModel, in order to use the submitChanges method, the callback of which, will be called once two of items are successfully created on the backend side (the below code example should be relevant for v2.ODataModel):
var oTableItemsBinding = oTable.getBinding("items");
// define the group ID, which will be used later on
var aCurrentDeferredGroups = oModel.getDeferredGroups();
oModel.setDeferredGroups(aCurrentDeferredGroups.concat("createProductGroup"));
// create two entries one by one, specifying the 'groupId' parameter
oModel.createEntry("/ProductSet", {
properties: contactEntry1,
groupId: "createProductGroup"
});
oModel.createEntry("/ProductSet", {
properties: contactEntry2,
groupId: "createProductGroup"
});
// send 2 requests in one $batch, passing the name of the 'groupId'
oModel.submitChanges({
groupId: "createProductGroup",
success: function() {
// no need to call refresh() as the model already does it by default (See "refreshAfterChange")
}.bind(this)
});
If your service does not support $batch requests, then you can still use the create method, but make use of it's success callback to be sure that the entry has been persisted in the backend.

Jquery Event handler not working when calling from page

I have written an event to save the data in a widget.js file & the handler is on the page. There is no error or exception is coming but the handler is not getting called. Please help.
Widget.js :
(function ($, undefined) {
$.widget('ui.discussionwidget', {
options: {
userID: 'arti.agarwa',
title: "",
width: "",
containerClass: ".ui-content-gutter"
},
saveData: function (userName, msg, parentID) {
//Save Discussion History
$.event.trigger({
type: "sendMessage",
userName: userName,
message: msg,
parentID: parentID,
timeStamp: new Date()
});
},
});})(jQuery);
Page Script :
$(document).ready(function () {
$('#discussionwidget').live("sendMessage", sendMessageHandler);
// sendMessage event handler
function sendMessageHandler(e) {
debugger;
alert(1);
}});
Looks like event delegation is not working fine with global events
$('#discussionwidget').on("sendMessage", sendMessageHandler);
Demo: Fiddle
I can see two possible problems:
Your widget has class discussionwidget but you are binding with id discussionwidget.
You are creating the widget dynamically with javascript? May be the event is being bound before the widget is created.
Try to fix both.

How to get a Custom ExtJS Component to render some html based on a bound value

I'm trying to get a custom extjs component to render either a green-check or red-x image, based on a true/false value being bound to it.
There's a couple of other controls that previous developers have written for rendering custom labels/custom buttons that I'm trying to base my control off but I'm not having much luck.
I'd like to be able to use it in a view as follows where "recordIsValid" is the name of the property in my model. (If I remove the xtype: it just renders as true/false)
{
"xtype": "booldisplayfield",
"name": "recordIsValid"
}
Here's what I have so far, but ExtJS is pretty foreign to me.
Ext.define('MyApp.view.ux.form.BoolDisplayField', {
extend: 'Ext.Component',
alias : 'widget.booldisplayfield',
renderTpl : '<img src="{value}" />',
autoEl: 'img',
config: {
value: ''
},
initComponent: function () {
var me = this;
me.callParent(arguments);
this.renderData = {
value: this.getValue()
};
},
getValue: function () {
return this.value;
},
setValue: function (v) {
if(v){
this.value = "/Images/booltrue.png";
}else{
this.value = "/Images/boolfalse.png";
}
return this;
}
});
I'd taken most of the above from a previous custom linkbutton implementation. I was assuming that setValue would be called when the model-value for recordIsValid is bound to the control. Then based on whether that was true or false, it would override setting the value property of the control with the correct image.
And then in the initComponent, it would set the renderData value by calling getValue and that this would be injected into the renderTpl string.
Any help would be greatly appreciated.
You should use the tpl option instead of the renderTpl one. The later is intended for rendering the component structure, rather that its content. This way, you'll be able to use the update method to update the component.
You also need to call initConfig in your component's constructor for the initial state to be applied.
Finally, I advice to use applyValue instead of setValue for semantical reasons, and to keep the boolean value for getValue/setValue.
Ext.define('MyApp.view.ux.form.BoolDisplayField', {
extend: 'Ext.Component',
alias : 'widget.booldisplayfield',
tpl: '<img src="{src}" />',
config: {
// I think you should keep the true value in there
// (in order for setValue/getValue to yield the expected
// result)
value: false
},
constructor: function(config) {
// will trigger applyValue
this.initConfig(config);
this.callParent(arguments);
},
// You can do this in setValue, but since you're using
// a config option (for value), it is semantically more
// appropriate to use applyValue. setValue & getValue
// will be generated anyway.
applyValue: function(v) {
if (v) {
this.update({
src: "/Images/booltrue.png"
});
}else{
this.update({
src: "/Images/boolfalse.png"
});
}
return v;
}
});
With that, you can set your value either at creation time, or later, using setValue.
// Initial value
var c = Ext.create('MyApp.view.ux.form.BoolDisplayField', {
renderTo: Ext.getBody()
,value: false
});
// ... that you can change later
c.setValue(true);
However, you won't be able to drop this component as it is in an Ext form and have it acting as a full fledged field. That is, its value won't be set, retrieved, etc. For that, you'll have to use the Ext.form.field.Field mixin. See this other question for an extended discussion on the subject.

afterrender not working for combobox when used in grid in EXTJS

This is my code for combo box inside grid:
{
header: 'FSCS',
dataIndex: 'acntOvrrideTypeCd',
flex: 1,
renderer: function(val, metaData, record, rowIndex, colIndex) {
var id = Ext.id();
var store = new Ext.data.Store({
fields: ['code', 'description'],
data: [{
"code": "",
"description": ""
}, {
"code": "E",
"description": "E"
}, {
"code": "D",
"description": "D"
}, {
"code": "S",
"description": "S"
}]
});
Ext.Function.defer(
(function() {
var cb = Ext.create('Ext.form.ComboBox', {
id: 'acntOvrrideTypeCd-' + rowIndex,
queryMode: 'local',
renderTo: id,
store: store,
forceSelection: true,
triggerAction: 'all',
lazyRender: true,
size: 5,
valueField: 'code',
displayField: 'description',
value: val
//listeners:{
// scope: this,
// 'select': Ext.getCmp('amlFscsForm').controller.amlShow(rowIndex)
//}
});
cb.on(afterrender, function() {
console.log("------- box---" + rowIndex);
Ext.getCmp('amlFscsForm').controller.amlShow(rowIndex);
});
}), 0.25);
console.log("i----------" + id);
return (Ext.String.format('<div id="{0}"></div>', id));
}
}
'afterrender' event is not fired. I need to enable or disable component after its rendered.
Can anyone help?
It's just a typo, afterrender should be in quotes otherwise you will just add the function for undefined event.
cb.on('afterrender',function(){
console.log("------- box---" + rowIndex);
Ext.getCmp('amlFscsForm').controller.amlShow(rowIndex);
});
There are a few problems with your code.
It looks like you're trying to create a combobox in the renderer function of a grid (your code at the top didn't get included in the code block). You're better off using the Ext.grid.plugin.CellEditing plugin instead, which will create a field on demand instead of when the column renders. Plus, every time your grid view refreshes you'll be creating another store and combobox for every row in the grid. Not good for performance, not good for the user experience either.
When calling defer, the duration is in milliseconds, not seconds. Also, you don't need to wrap the function in parenthesis. Just give it the function itself. Like this:
Ext.defer(function(){
// do stuff
}, 25);
Setting lazyRender to true only works if your component is the child of some container that doesn't render all its components immediately (like a tabpanel).
It may be easier to just set the disabled config in the combobox when you create it instead of when you render it, unless you don't have the information available at creation time.
Like nscrob said, when using the on method you need to specify the event as a string. If you use the listeners config (which you have commented out), you can just do:
listeners: {
afterrender: function(){
console.log("------- box---" + rowIndex);
Ext.getCmp('amlFscsForm').controller.amlShow(rowIndex);
},
select: function(){
Ext.getCmp('amlFscsForm').controller.amlShow(rowIndex);
}
}
It's important to note that the scope of these listener functions defaults to the component itself (your combobox) so scope: this is unnecessary. Unless you want the scope to be whatever object is creating this combobox, that is.
The first point is the most important. Look into using the CellEditing (or RowEditing) plugin and I guarantee things will go a lot more smoothly.

Categories

Resources