1

Topic: Dynamically updating a listbox

I'm trying to migrate a 3.x plugin to 4.x, largely by moving functionality from what had been an externally-loaded PHP script, into "pure TinyMCE" javascript.

My PHP script had a series of SELECT menus, and I used AJAX calls to dynamically update their contents.

The new version -- I'm basing it on the 4.x "link" plugin -- builds the series of ListBoxes using TinyMCE Control syntax:

moduleListCtrl = {
    name: 'mmodule',
    type: 'listbox',
    label: 'Module',
    values: buildmoduleList(),
    onselect: moduleListChangeHandler
};
classListCtrl = {
    name: 'mclass',
    type: 'listbox',
    label: 'Class',
    values: buildclassList()
};

and those are passed into an editor.windowManager.open() call, where they are rendered into fancy TinyMCE controls by virtue of some magic I have not discovered yet (the means by which the "body" parameters are converted to HTML is not very well documents).

I have an AJAX call in the moduleListChangeHandler function, which I use to fetch a new list of values that are intended to REPLACE the values in the control built by classListCtrl.

So far, however, I haven't figured out how to get the new values into the existing rendered classListCtrl ListBox. Normally I'd handle such things with DOM manipulation, but the ListBox HTML is complicated, and it seems like there should be a more integrated way to do it.

Can anyone provide an example?

Do I replace the values of classListCtrl, and call repaint()? Do I get the parent container of classListCtrl and tell it to replace the entire classListCtrl with a "newClassListCtrl"? And then "reflow()"?

This seems like it should be easy, but hasn't been so far!

2

Re: Dynamically updating a listbox

This is how i did it. There may be a better way


tinymce.PluginManager.add('myexample', function(editor, url) {
   var self = this, button;
   
   function getValues() {
      return editor.settings.myKeyValueList;
   }

   // Add a button that opens a window
   editor.addButton('myexample', {
      type: 'listbox',
      text: 'My Example',
      values: getValues(),
      onselect: function() {
         //insert key
         editor.insertContent(this.value());
         
         //reset selected value
         this.value(null);
      },
      onPostRender: function() {
         //this is a hack to get button refrence.
         //there may be a better way to do this
         button = this;
      },
   });
   
   self.refresh = function() {
      //remove existing menu if it is already rendered
      if(button.menu){
         button.menu.remove();
         button.menu = null;
      }
     
      button.settings.values = button.settings.menu = getValues();
   };
});



Call following code block from ajax success method

//Set new values to myKeyValueList
tinyMCE.activeEditor.settings.myKeyValueList = [{text: 'newtext', value: 'newvalue'}];

//Call plugin method to reload the dropdown
tinyMCE.activeEditor.plugins.myexample.refresh();

3

Re: Dynamically updating a listbox

I'm working on an extended version of the Template plugin which will need three listboxes when done, as part of work on experimenting with using TinyMCE instead of a competing editor in our product, ProVerbial.

This is a work in progress, but the function onSelectOrderType() shows how to dynamically update a listbox. Basically, each of the templates in the list returned by the XHR contains an attribute 'afts' which is an array of items (second listbox) related to the order type (first listbox).

My code is based on the Template plugin (from TinyMCE 4.1.6) (some irrelevant code cut):

tinymce.PluginManager.add('pvbTextTemplateSelection', function(editor, url) {
    var each = tinymce.each;

    function createTemplateList(callback) {
        return function() {

            tinymce.util.XHR.send({
                          cut…
            });
        };
    }

    function showDialog(templateList) {
        var win, values = [], templateHtml;

        if (!templateList || templateList.length === 0) {
            editor.windowManager.alert('No templates defined');
            return;
        }

        // Entries for the first listbox
        tinymce.each(templateList, function(template) {
            var orderTypeListEntry = {
                                      selected: !values.length,
                                    text: template.title,
                                    value: {
                                        url: template.url,
                                        content: template.content,
                                        description: template.description,
                                        afts: [] // Contains the related entries for the second listbox
                                    }
                                };
           
            values.push(orderTypeListEntry);
           
            // Related entries for the second listbox
            tinymce.each(template.afts, function(aft) {
                orderTypeListEntry.value.afts.push({
                    selected: false,
                    text: aft,
                    value: {
                        description: aft,
                        content: 'Content.'+aft
                    }
                });
            });
        });

        function onSelectOrderType(e) {
            var value = e.control.value();
           
            var listbox = win.find('#aft')[0]; // Find the second listbox

            var container = win.find('container')[0]; // Find the container around the listboxes
            var newListbox = container.create({ type: 'listbox', label: 'AFT', name: 'aft', values: value.afts, onselect: onSelectAFT});  // Create the replacement listbox
           
            container.replace(listbox, newListbox[0]); // Replace the old with the new
            container.renderNew(); // Show the new listbox. Without this, the new listbox is never drawn
        }

        function onSelectAFT(e) {
            cut… // Actions on selecting an entry in the second listbox
        }

        win = editor.windowManager.open({
            title: 'Textbaustein einsetzen',
            layout: 'flex',
            direction: 'column',
            align: 'stretch',
            padding: 15,
            spacing: 10,

            items: [
                {type: 'form', flex: 0, padding: 0, items: [
                    {type: 'container', label: 'Order Type/AFT', items: [{
                        type: 'listbox', label: 'Order Type', name: 'ordertype', values: values, onselect: onSelectOrderType
                    },
                    { type: 'listbox', label: 'AFT', name: 'aft', values: [{selected: true, text: 'Dummy', value: 'DummyValue'}], onselect: onSelectAFT}]}
                ]},
                {type: 'label', name: 'description', label: 'Description', text: '\u00a0'},
                {type: 'iframe', flex: 1, border: 1}
            ],

            onsubmit: function() {
                insertTemplate(false, templateHtml);
            },

            width: 1000,
            height: 800
        });

        win.find('listbox')[0].fire('select');
    }

        Rest cut, basically "Template" plugin code adjusted to the new plugin name

Last edited by sbuf (2014-10-30 00:57:46)

4

Re: Dynamically updating a listbox

I want to add plug in to delete template. for this I am using same form like template.

For deleting selected template I want the selected value from listbox which contains list of inserted templates. I have used various ways to get it but no luck.


1. var selectedValue = win.find('#listbox')[0].value();

2. getContent() is also not working.


I am getting "null" value or undefined value.


Please suggest me solution for this.

Thank you.

Last edited by amruta (2016-08-29 12:10:07)

5

Re: Dynamically updating a listbox

The solution is the first line of onSelectOrderType() above.

6

Re: Dynamically updating a listbox

Thanks for the solution. I have tried

var value = e.control.value();

getting blank(' ') value.

I have also tried code 'value.content' , is giving the all contents of template. but I want template name.

Please sugget my any property for this.

7

Re: Dynamically updating a listbox

I've updated my code since my original post. I now create a listbox with

{
                    type : 'listbox',
                    label : 'pvb.templates.selection.label.language_selection',
                    onclick : function() {
                        onSelectLanguage(this.value());
                    },
                    values : languages,
                    value : selectedLanguage
                }

The 'onclick' handler calls my function with the selected value of the listbox.

8

Re: Dynamically updating a listbox

This also not working for me. I am getting '[object][object]'  as a value.