–1 vote

Hello, I have a simple question.

I would like to know how to get LOOKUPMASTER/LOOKUPDETAIL with a multivalue field for LOOKUPDETAIL.

Thanks by advance.

asked in Efficy/ Client side by (110 points)

3 Answers

0 votes
Best answer

Hi Mathieu,

For my part I will go with the following solution :

0- in your Lookup which will be used for the multivalue, add the key (here K_CASE_SERVICE) column which will point to the LK_CASE_SERVICE

1- Set a new Form Edit Definition for your multivalue field, this definition is base on the standard one call "MULTIVALUE" at the exception that it is calling the macro "CaseMotifJsonMultiValueList" instead of "JsonMultiValueList"

in FormFieldEditCustom.txt

field.F_MOTIF {[
data-json='{<%GetField("$FIELD$", type="MULTIVALUE", json=T, context=ATTR)%>}')%>

2- Create the macro "CaseMotifJsonMultiValueList", which will return an array of object used to publish the list of available options : [{"id":xx, "text":'option value 1'},{"id":yy, "text":'option value 2'},...]

CaseMotifJsonMultiValueList {[<%RunQuery(id="CaseMotif", SQL=|select K_CASE_MOTIF, F_MOTIF
from <#table name="LK_CASE_MOTIF"> LK_CASE_MOTIF
where (DISABLED = '0' and K_CASE_SERVICE = :param1)
and (
lower(F_MOTIF) like '%' + lower(:param2) + '%'
order by F_MOTIF|,
param1="%%OnArgument('K_CASE_SERVICE',value='',then='0', else=`%%GetArgument('K_CASE_SERVICE', context=TAG)`)",
  param2="%%OnArgument('search',value='',then='%', else=`%%GetArgument('search', context=TAG)`)",
[<%GetDataGrid(query="CaseMotif", count=-1, TemplateText=|<#repeat>{"id": <#F=K_CASE_MOTIF;context=JS>, "text": "<#F=F_MOTIF;context=JS>"}<#S=;SEPARATOR=,></#repeat>|)%>]

3- Now you have to past the value of the Master field (here it is F_SERVICE) to the ajax call of the Multivalue field.
for that you can override the editView.js the following way, I have added the //CUSTOM to indicate what I have customized.

], function (require, $, Paperboy, moment, select2, Const, Model, CKEDITOR, format, Url, Swipe, Display, FileHelper, EditEntityGrid, Utils, OverlayView, standardEditView) {
console.log('editView Custom... starting');

standardEditView.start = function() {
if (Model('editHandle') && Url.getArgument('edithandle') === '')
history.pushState({}, window.title, location.href + '&edithandle=' + Model('editHandle')); // reuse edit context for first F5
.on('ajaxStart.eff.editview', this._ajaxStart.bind(this))
.on('ajaxStop.eff.editview', this._ajaxStop.bind(this))
.on('touchstart.eff.editview touchmove.eff.editview touchend.eff.editview',
{name: 'editview', container: $('#edit-main'), isValidStart: this._swipeIsValid.bind(this), eventTouchEnd: this._swipeCallback.bind(this)},
function(e) { Swipe.swipe(e); })
.on('rename.eff.filehelper', this._state.bind(this))
.on('edit.eff.filehelper', this._fileEdit.bind(this))
.on('download.eff.filehelper upload.eff.filehelper', this._fileProgress.bind(this))
.on('select.eff.filehelper', this._fileSelect.bind(this))
.on('print.eff.filehelper', this._filePrint.bind(this))
.on('error.eff.sidebar', this._sidebarError.bind(this))
.on('status.eff.sidebar', this._sidebarStatus.bind(this));

$('#dd-dropdown-host, #dd-dropdown-host-medium').on('loaded.fndtn.dropdown', function () {
$(':first-child', this).focus();
$('#tab-files-menu').on('afteropened.fndtn.dropdown.filehelper', this._fileMenuOpened.bind(this));

if (!top.name && + Model('key') > 0)  //set a window name if none to avoid concurrent edit windows
top.name = Model('entity') + 'EditNew' + Model('key');


$('#ROBINSON').on('change', function () {
Paperboy.publish(Const.VIEW_CHANNEL + 'edit/main', ['robinson'], this);
$(document).ready(function () {
if (typeof window.AfterLoaded === 'function')
// Master/detail
$('[data-associated-fields]').on('change', function () {
var i, elem, associatedFields = this.getAttribute('data-associated-fields');
if (associatedFields) {
associatedFields = associatedFields.split(';');
i = associatedFields.length;
while (i--) {
elem = document.getElementById(associatedFields[i]);
if (elem)

switch (Model('entity')) {
case 'Acti':
$(document).on('dp.show dp.change', this._setDuration);
case 'Case': //CUSTOM : empty the F_MOTIF field (multivalue field) when the Master field F_SERVICE change
var $service = $('#F_SERVICE');
if ($service.length > 0) {
$service.on('change', function () {
case 'Comp':
if (Model('inserted') === 1) {
var $vat = $('#VAT');
$vat.attr('data-delayed-msg', 'searchSimilar;Comp;VAT');
$vat.attr('data-channel', 'edit/main');
var $web = $('#WEB1');
$web.attr('data-delayed-msg', 'searchSimilar;Comp;Web;7');
$web.attr('data-channel', 'edit/main');
case 'Cont':
if (Model('inserted') === 1) {
var $mail = $('#EMAIL1');
$mail.attr('data-delayed-msg', 'searchSimilar;Cont;Mail');
$mail.attr('data-channel', 'edit/main');
case 'Docu':
var tabFilesSel = '#tab-files',
$tabFiles = $(tabFilesSel),
fileId = Url.getArgument('selFileId');
if (fileId && $tabFiles.length) {
var $f = $tabFiles.find('[data-file-id=' + fileId + ']');
if ($f.length) {
$(document).foundation('tab', 'activate_tab', tabFilesSel);
$('#CATEGORY-DOCU$INVOICING-CURRCY').on('change', this._confirmCurrencyChange);
case 'Oppo':
$('#CURRCY').on('change', this._confirmCurrencyChange);
.on('keydown.eff.closeContext keypress.eff.closeContext keyup.eff.closeContext', this._onOppoEditProdKeyEvent.bind(this))
.on('reload', this._onOppoEditProdReload.bind(this))
case 'Quer':
case 'Tmpl':


standardEditView._initSelect2 = function() {
//TRW: jQuery selectors. Not visible select = already implemented as select2 or not in current tab
var $container = $('#category-contents');
$('select', $container.children('.content:not(.category)')).filter(':not(.no-select2):visible').select2(
allowClear:    true,
closeOnSelect: false
$('input[data-ajax-url]', $container).filter(':not(.no-select2):visible').select2(
multiple:      true,
ajax:          {
dataType:    'json',
cache:       true,
data:        function (term) { 
if (Model('entity') == 'Case' && $('#F_SERVICE').length > 0) { //CUSTOM : Past the value of the master field (F_SERVICE) to the ajax that is calling the data-ajax-url as an arguement
return term ? {search: term, K_CASE_SERVICE: $('#F_SERVICE').val()} : {K_CASE_SERVICE: $('#F_SERVICE').val()}; 
} else 
return term ? {search: term} : {}; 
results:     function (data) { return {results: data}; }
initSelection: function (element, callback) {
var json, keys, i,
data = [];
try {
json = JSON.parse(element.attr('data-json'));
keys = Object.keys(json);
i = keys.length;
while (i--) {
var key = keys[i];
data[i] = {id: key, text: json[key]};
catch (e) {}
closeOnSelect: false,
separator:     ';'

return standardEditView;


and this is it :)

answered by (1.9k points)
selected by
This is overkill, as I said the server side filtering of the multi values works out of the box. The only issue is that on a change of the master lookup field, the value is not posted to the server. Is this even handled in your scenario?
Yes it is, check comment in editView.js : //CUSTOM : empty the F_MOTIF field (multivalue field) when the Master field F_SERVICE change

PS: until now this was not working in Efficy Standard... so we had to find the solution quickly for the customer... if you have a better one ... post it ;)
0 votes

I tested it with 11.2 and it doesn't work out of the box client side. Server side everything works well, but the problem is that the master value is not pushed to the server with a CebState. This does happen for slave lookups with the following conditions:

The master-detail works for normal lookups in these two situations only:

  • In X-Y Grid when the edit style of the slave lookup is set to "Look-up with dropdown window" or with "Look-up with search window". Not with "Look-up with dropdown list"
  • In a form when using definition LOOKUPDROPDOWN or LOOKUPDROPDOWNSEARCH. Not with LOOKUP

In my opinion, you can create a case as raise this as a technical issue. Multi values in slave should at least work in forms

answered by (7.4k points)
Thanks for your answer Kristof. I will see that then. Have a nice day!
0 votes

Thanks both for your answers, it helped me! Have a nice day :)

answered by (110 points)
1,248 questions
1,518 answers
328 users