I'm trying to pass function from MVC model to fullcalendar CustomButton like so
var model = new CalendarViewModel()
{
(...different properties of fullcalendar...)
CustomButtons = new
{
CustomButton = new
{
Text = "Custom",
Click = "function() { window.location.href = " + Url.Action("CustomView", "Custom") + "; }"
}
},
Header = new { Center = "title", Left = "prev,next customButton", Right = "month,agendaWeek,agendaDay,today" },
};
And then serialize and pass it to js file
function initFrom(calendarViewModel, rootUrl) {
$('#calendar').fullCalendar(calendarViewModel);
}
However I get error customButtonProps.click.call is not a function which I belive is caused because I'm passing string from serialized model.
If my approach is incorrect how can I achieve desired result - passing routing values to custom button click function (without hardcoding route values inside js file)?
I found a workaround for this.
Based on this scheduler demo I've appended custom button in JS and retrieved values from passed model (with a slight changes in model which I'm omitting here):
$('.fc-toolbar .fc-left').append(
$('<div class="fc-button-group"><button type="button" class="ui-button ui-state-default ui-corner-left ui-corner-right ui-state-hover">' + calendarViewModel.customButton.text + '</button></div>')
.on('click', function () {
location.href = calendarViewModel.customButton.url;
})
);
Related
I would like to create a custom widget that will display several widgets within it. For example, I would like a custom widget to be composed of a listview, a combobox, a calender, and a menu. Is this possible?
What I am thinking is adding the HTML in the refresh method, then initialize DOM elements such as below. I would like to use MVVM as well.
refresh: function() {
var that = this,
view = that.dataSource.view(),
html = kendo.render(that.template, view);
// trigger the dataBinding event
that.trigger(DATABINDING);
// mutate the DOM (AKA build the widget UI)
that.element.html(html);
// is this safe???
kendo.bind(that.element, { source: this.dataSource });
// or do this???
this.element.find('.listview').kendoListView({ dataSource: this.dataSource });
// trigger the dataBound event
that.trigger(DATABOUND);
}
It feels weird to call a kendo.bind in a widget where it is probably initialized via Kendo MVVM as well. Is there a better way to do this?
Yes it is possible, you have to create a plugin of yours which will generate the controls, You can refer the ways to create a plugin.
create basic jquery plugin
Below code is just a sample to help you start with, it is not a running code. You can modify this and make it run as per your requirement
I have created a sample for binding combobox, you can add up other controls in the same manner.
$.fn.customControl = function (options) {
var settings = $.extend({}, options);
return this.each(function () {
var $this = $(this);
var comboboxDatasource, listviewDatasource, menuDatasource; // as many controls you want to bind
$.each(settings.controls, function (index, value) {
switch (value.type) {
case "combobox":
comboboxDatasource = value.datasource;
var $combobox = "<input data-role='combobox' " +
" data-text-field='" + value.textField + "'" +
" data-value-field='" + value.valueField + "'" +
" data-bind='source: '" + value.datasource + "'," +
" events: {" +
" change: onChange," + //pass it in the custom control parameters if you want to have a custom event for the control
" }' />";
$this.append($combobox); // Appends a control to the DOM which can be later bound to data using MVVM kendo.observable
break;
case "listview":
//Create listview and other controls as demo'ed for the combobox.
break;
case "calendar":
break;
case "menu":
break;
}
});
//Create the kendo Observable object to bind the controls
var viewModel = kendo.observable({
comboboxDatasourceProperty: new kendo.data.DataSource({ //Fetch the datasource for each list control based on the parameters sent
transport: {
read: {
url: "url to datasource",
dataType: "dataType you want e.g. jsonp"
}
}
}),
listviewDatasourceProperty: function () { },
menuDatasourceProperty: function () { }
});
// Bind the View to the div which contains all the other controls
kendo.bind($($this), viewModel);
}); // return this.each
}; //customControl
Basic settings to use it is to create a div in the page which will actually contain all the other controls
<div id="customControlDiv"></div>
In the page you can use the control as below to create and bind the controls, if you want to bind it to the refresh function in observable then, write the below code within the refresh function
$("customControlDiv").customControl({ controls: [
{ type:'listview',id:'listviewID',datasource='path to datasource for listview',textField='text',valueField='id' }, //if you want to pass your datasource url, make a prop. and pass the url
{ type:'combobox',id:'comboboxID',datasource='path to datasource for combobox',textField='id',valueField='id' }, // which can be accessed in the plugin to fetch datasource
{ type:'calendar',:'calenderID',datasource='',textField='',valueField='' },
{ type:'menu',id:'menuID',datasource='path to datasource for menu',textField='text',valueField='id' }
]
});
Hope this helps :)
I'm using jQuery dataTables to display a table. I need to be able to pass a row selection event on to my Aura component that handles the selection and performs some operations on the data from that row.
In the initialize() function:
initialize: function()
{
$("#mytable tbody").click(function(event)
{
$(mytable.fnSettings().aoData).each(function ()
{
$(this.nTr).removeClass('row_selected');
});
$(event.target.parentNode).addClass('row_selected');
});
mytable = $('#mytable').dataTable();
},
I set up the click handler for the row selection, but how do I get a reference to the enclosing component so I can sandbox.emit() function to issue messages? I can put a reference to the component into the Closure, but that essentially makes this component a singleton and I could never have two instances of the component on the page at the same time.
Is there a standard way, using jQuery selectors or some other method, that I can retrieve a reference to the enclosing component from inside the click() handler?
Edit: I should never try to write code until I have had 32oz of caffine. You can pass a reference to the current component via the click() method itself. Like so:
$("#mytable tbody").click(this, function(event)
{
$(mytable.fnSettings().aoData).each(function ()
{
$(this.nTr).removeClass('row_selected');
});
$(event.target.parentNode).addClass('row_selected');
event.data.sandbox.emit('mychannel', {data: 'stuff'});
});
If I understand your question correctly, you could try something like this
initialize: function () {
var that = this;
$("#mytable tbody").click(function(event) {
//have acces to component as 'that'
});
}
what I used for events is view inside component configuration:
View: {
events: {
'click a[data-question-edit-id]': function (e) {
var button = $(e.currentTarget),
id = button.attr('data-question-edit-id'),
examId = this.component.examModel.get('id');
this.sandbox.router.navigate('/exams/' + examId + '/questions/' + id + '/edit', {trigger: true});
},
'click a[data-question-delete-id]': function (e) {
var button = $(e.currentTarget),
id = button.attr('data-question-delete-id');
this.component.showDeleteConfirmation(id);
}
}
}
If you'll find be helpful, here is my repo of aura project I'm working on:
https://github.com/lyubomyr-rudko/aura-test-project
I am creating list of <span class="infa9span"><img src="/csm/view/include/images/foldericon.png"/><a id="infa9Service">'+servicename+'</a><br/></span> tags dynamically and appending it to a div
Then using the below map to map a tags attribute to some function
var idMap = {
//it can be a lot more
"javaInfo":javaInfo,
/*infa9 product map*/
"infa9PMServer":infa9PMServer,
"infa9Service":infa9Service
};
This is the click Handler
$('#ds-accordion a').click(function(event) {
var elementId=$(this).attr("id");
treeItemClickHandler(elementId);
});
function treeItemClickHandler(id)
{
(idMap[id])(id); //Is this usage called 1st class functions?
}
function infa9Service(id)
{
alert("i got this "+id);
}
Note: I am using Jquery v1.6.3
But when I click on any of the a tags, it calls the function an does all the operation inside the function, but gives an error Object dosen't support this porperty or method in the treeItemClickHandler function.
I would like to know,
How to avoid getting this error?
Is there a more better approach for something like this?
And Is it 1st class functions that I am using (if so where can i learn more about it)?
Thanks.
Update
How can I pass 2nd parameter?
'<span class="infa9span"><img src="/csm/view/include/images/foldericon.png"/><a id="infa9Service" title='+servicename+'>'+servicename+'</a><br/></span>'
$('#ds-accordion a').click(function(event) {
var elementId=$(this).attr("id");
var elementName=$(this).attr("title");
treeItemClickHandler(elementId,elementName);
});
function treeItemClickHandler(id,name)
{
idMap[id](id,name);
}
function infa9Service(id,name)
{
alert(id+", "+name);
}
It gives me infa9Service, undefined
check this out http://jsfiddle.net/ywQMV/4
1)define your functions.
2)define your id map.
html part :
<div id ="ds-accordion">
<span class="infa9span">
<img src="/csm/view/include/images/foldericon.png"/>
<a id="infa9Service" title='+servicename+'>'+servicename+'</a>
<br/>
</span>
js part:
function infa9Service(id, serviceName)
{
alert("i got this "+id +" serviceName : " + serviceName);
}
var idMap = {
"infa9Service":infa9Service
};
$('#ds-accordion a').click(function(event) {
var elementId=$(this).attr("id");
var serviceName = this.title;
treeItemClickHandler(elementId, serviceName);
});
function treeItemClickHandler(id,serviceName)
{
// alert(idMap[id])
(idMap[id])(id,serviceName); //Is this usage called 1st class functions?
}
I'm not an expert of jquery and i need help to porting this function
auto_complete: function(controller, focus) {
if (this.autocompleter) {
Event.stopObserving(this.autocompleter.element);
delete this.autocompleter;
}
this.autocompleter = new Ajax.Autocompleter("auto_complete_query", "auto_complete_dropdown", "/admin/" + controller + "/auto_complete", {
frequency: 0.25,
afterUpdateElement: function(text, el) {
if (el.id) {
window.location.href = "/admin/" + controller + "/" + escape(el.id);
} else {
$("auto_complete_query").value = "";
window.location.href = window.location.href;
}
}
});
$("auto_complete_dropdown").update("");
$("auto_complete_query").value = "";
if (focus)
$("auto_complete_query").focus();
},
Anyone may help me?
Although that uses some Prototype calls, that's actually mostly just using a script.aculo.us auto-completer; you'll want to find a similar widget for jQuery (there's one listed on the jQuery plug-ins page) and then rewrite the code to do the same thing using that plug-in. Looks like mostly what it does is navigate to "/admin/mumble/id" where "mumble" is the value of the pass-in controller variable and "id" is the ID of the element chosen in the auto-completer.
I'm trying to bind an onChange event of one FilteringSelect to populate another FilteringSelect.
// View
dojo.addOnLoad(function () {
dojo.connect(dijit.byId('filterselect1'), 'onChange', function () {
dijit.byId('filterselect2').store = new dojo.data.ItemFileReadStore(
{ url: "/test/autocomplete/id/" + dijit.byId("filterselect1").value }
);
});
});
The JSON is generated from what I can tell correctly from a Zend Action Controller using a autoCompleteDojo helper.
// Action Controller
public function autocompleteAction()
{
$id = $this->getRequest()->getParam('id');
$select = $this->_table->select()
->from($this->_table, array('id','description'))
->where('id=?',$id);
$data = new Zend_Dojo_Data('id', $this->_table->fetchAll($select)->toArray(), 'description');
$this->_helper->autoCompleteDojo($data);
}
I receive the JSON from the remote datastore correctly, but it does not populate the second FilteringSelect. Is there something else I need to do to push the JSON onto the FilteringSelect?
I couldn't believe this was causing the problem, but the whole issue boiled down to the fact that it appears that a dojo ItemFileReadStore REQUIRES the label property of the JSON to be "name". In the end this is all that it required to wire them together.
dojo.addOnLoad(function () {
dijit.byId('filtering_select_2').store = new dojo.data.ItemFileReadStore({url: '/site/url'});
dojo.connect(dijit.byId('filtering_select_1'), 'onChange', function (val) {
dijit.byId('filtering_select_2').query.property_1 = val || "*";
});
});
UPDATE: The property within Zend form has been fixed as of ZF 1.8.4
Try console.log() in the event to see if it is launched. Changing the store should work, however for other widgets like grid you have also to call refreshing methods.