Open dberansky opened 11 years ago
hi, could you clarify what you mean under "dropdown as one of its subcomponents" ?
Let's take the address custom component as an example. let's say I want the city field to be a dropdown rather than just a text field. Furthermore, I need that dropdown's options to be dynamically populated (via ajax).
thanks
ok, now I get it :) you can modify address as following:
input[type=text]
with select
in template source
option (declare it in defaults). You should return deferred object to deal with async ajax. See for ex render
in https://github.com/vitalets/x-editable/blob/master/src/inputs/list.jsOh, I see... I was thinking more along the lines of re-using x-editable's own dropdown widget, the one used for editing of 'select', since it already implements all the functionality I need. Is that a possibility? I've been looking at the source for how the editable select widget is implemented, but so far haven't been able to figure out how to reuse it.
ok, may be another approach:
inherit your custom widget from current select
and add to template one more input (e.g. type=text
). Also you need to overwrite some methods (e.g. input2value
etc) to ensure correct passing value from and to widget.
Let me know about your progress as it's very good usecase.
thx!
Any updates on this issue? Do you have an example hat I could use?
Yeh, sorry it has taken me so long to get back. I just recently managed to work on this again. The code's below. It's not exactly what I wanted (I'd prefer the select to be a true combobox capable of taking a value not currently in the suggestion list) but is good enough as an example.
/**
Contact Info editable input.
@class contactinfo
@extends abstractinput
@final
@example
<a href="#" id="contact" data-type="contactinfo" data-pk="1">awesome</a>
<script>
$(function(){
$('#contact').editable({
url: '/post',
title: 'Enter contact info',
value: {
role: 'email',
text: 'me@gmail.com'
}
});
});
</script>
**/
(function ($) {
var ContactInfo = function (options) {
this.init('contactinfo', options, ContactInfo.defaults);
};
//inherit from Abstract input
$.fn.editableutils.inherit(ContactInfo, $.fn.editabletypes.select);
$.extend(ContactInfo.prototype, {
value2input: function(value) {
console.log(value);
if(!value) {
return;
}
this.$input.filter('select').val(value.role);
this.$input.filter('input').val(value.text);
},
input2value: function() {
return {
role: this.$input.filter('select').val(),
text: this.$input.filter('input').val()
}
},
value2html: function(value, element) {
$(element).html(value.role+": "+value.text);
},
str2value: function(str) {
if( !str || !(typeof(str) === 'string'))
return str;
var splitPos = str.indexOf(':');
if(splitPos < 0)
return str;
var type = str.substr(0,splitPos).trim();
var text = str.substr(splitPos+1).trim();
return {role:type, text:text}
}
});
ContactInfo.defaults = $.extend({}, $.fn.editabletypes.select.defaults, {
tpl: '<select class="input-medium"></select>'+
'<input type="text" name="contact_value" style="margin-left: 1em;" class="input-medium" size="12" placeholder="contact">',
inputclass: ''
});
$.fn.editabletypes.contactinfo = ContactInfo;
}(window.jQuery));
Wow dbransky, it works! Some minor corrections:
value: {
role: email,
text: me@gmail.com
}
should be:
value: {
role: 'email',
text: 'me@gmail.com'
},
And I needed to add a source for the dropdown:
<a href="#" id="contact" data-type="contactinfo" data-pk="1"
data-source="[{value: 'email', text: 'email'},{value: 'postcode', text: 'Postcode'}]"
>awesome</a>
One other thing for anyone interested: the data arrives server-side as (php in this example)...
Array
(
[role] => email
[text] => me@gmail.com
)
thanks, fixed the missing quotes in comment doc
Hi all, I have a similar issue but i am not able to figure this out. I have a text field and a select box and i want to load select options from an ajax call. Here my code:
(function ($) {
"use strict";
var ModelData = function (options) {
this.source = options.source;
this.init('modelData', options, ModelData.defaults);
};
//inherit from Abstract input
$.fn.editableutils.inherit(ModelData, $.fn.editabletypes.select);
$.extend(ModelData.prototype, {
/**
Renders input from tpl
@method render()
**/
render: function () {
this.$input = this.$tpl.find('textarea');
this.$select = this.$tpl.find('select');
this.$select.empty();
var fillItems = function ($el, data) {
if ($.isArray(data)) {
for (var i = 0; i < data.length; i++) {
$el.append($('<option>', {
value: data[i].value
}).text(data[i].text));
}
}
return $el;
};
var deferred = $.Deferred();
this.error = null;
this.onSourceReady(function () {
console.log(this.source());
fillItems(this.$select, this.source());
deferred.resolve();
}, function () {
this.error = this.options.sourceError;
deferred.resolve();
});
return deferred.promise();
},
/**
Default method to show value in element. Can be overwritten by display option.
@method value2html(value, element)
**/
value2html: function (value, element) {
if (!value) {
$(element).empty();
return;
}
var relationshipText = value.relationship;
$.each(this.source, function (i, v) {
if (v.value === relationshipText) {
relationshipText = v.text;
}
});
value.noteView = value.note ? value.note : 'n/a';
var html = '<div class="col-md-12"><span class="col-dataset">RELATIONSHIP: </span>' +
'<span class="editable-post-select" data-type="select" data-pk="1" data-value="' + value.relationship + '" style="font-size: 12px;">' +
relationshipText +
'</span>' +
'</div>' +
'<div class="col-md-12"><span class="col-dataset">NOTE: </span>' +
'<span class="editable-post-textarea" data-type="textarea" data-pk="2" data-value="' + value.note + '"style="font-size: 12px;">' +
value.noteView +
'</span>' +
'</div>';
$(element).html(html);
},
/**
Gets value from element's html
@method html2value(html)
**/
html2value: function (html) {
return null;
},
/**
Converts value to string.
It is used in internal comparing (not for sending to server).
@method value2str(value)
**/
value2str: function (value) {
var str = '';
if (value) {
for (var k in value) {
str = str + k + ':' + value[k] + ';';
}
}
return str;
},
/*
Converts string to value. Used for reading value from 'data-value' attribute.
@method str2value(str)
*/
str2value: function (str) {
/*
this is mainly for parsing value defined in data-value attribute.
If you will always set value by javascript, no need to overwrite it
*/
return str;
},
/**
Sets value of input.
@method value2input(value)
@param {mixed} value
**/
value2input: function (value) {
if (!value) {
return;
}
this.$select.val(value.relationship);
this.$input.filter('[name="note"]').val(value.note);
},
/**
Returns value of input.
@method input2value()
**/
input2value: function () {
return {
relationship: this.$select.val(),
note: this.$input.filter('[name="note"]').val()
};
},
/**
Activates input: sets focus on the first field.
@method activate()
**/
activate: function () {
this.$select.focus();
}
});
ModelData.defaults = $.extend({}, $.fn.editabletypes.select.defaults, {
tpl: '<div class="form-group">' +
'<label for="relationship" class="col-sm-2 control-label col-dataset">RELATIONSHIP:</label>' +
'<div class="col-sm-4"><select name="relationship" class="input-sm form-control"></select></div>' +
' </div> ' +
'<div class="form-group">' +
'<label for="note" class="col-sm-2 control-label col-dataset">NOTE:</label>' +
'<div class="col-sm-9"><textarea rows="1" name="note" class="input-sm form-control"></textarea>' +
' </div>' +
' </div> ',
inputclass: '',
source: []
});
$.fn.editabletypes.modelData = ModelData;
}(window.jQuery));
$(function () {
$.fn.editable.defaults.mode = 'inline';
$('.editable-post-select').off('click');
$('.editable-post-textarea').off('click');
$('.edit-post-button').each(function () {
$(this).parent().prev().children('.modelData').editable({
toggle: 'manual',
url: $(this).attr('href'),
pk: 1,
name: 'modelData',
value: {
relationship: $(this).siblings('input[name="referenceRelationship"]').val(),
note: $(this).siblings('input[name="referenceNote"]').val()
},
source: function () {
var tmp = null;
$.ajax({
url: "dataset/relation",
async: true,
success: function (data) {
tmp = data;
}
});
return tmp;
},
highlight: false,
validate: function (value) {
if (value.relationship === '')
return 'Relation with model is required.';
},
success: function (response, newValue) {
if (response.valid === true) {
message = 'The dataset has been successfully updated!';
type = 'success';
} else {
message = 'There has been an error during saving. Please contact the MIDAS support.';
type = 'danger';
}
$.bootstrapGrowl(message, {
element: 'body',
type: type,
offset: {from: 'bottom', amount: 50},
align: 'left',
width: 350,
delay: 4500,
allow_dismiss: true
});
$('#can-reload').attr('value', true);
}
});
$(this).click(function (e) {
e.preventDefault();
e.stopPropagation();
$(this).parent().prev().children('.modelData').editable('toggle');
$('form').removeClass('form-inline').addClass('form-horizontal');
});
});
});
Hello, I have to display some tooltip for each dropdown item. How to do this?
Hi,
Any pointers on how to implement a custom widget that has a select dropdown (populated from array/function/ajax) as one of its subcomponents?
Thanks D.