Expand my Community achievements bar.

SOLVED

Drop-down list automatic add-on

Avatar

Former Community Member

Is is possible to make a drop-down list add a new list item every time someone inputs something that's not already in the list?

Thanks,

Josh

1 Accepted Solution

Avatar

Correct answer by
Former Community Member
  • The script adds one "custom" name. Subsequent names overwrite the original. Is it possible to have the ability to add an unlimited number of additional items to the dropdown?

OK and think v1.1 solves this problem. Testing, sorry, more testing may prove me wrong. The array has to be initialized in the body of a function, otherwise it gets created anew on each call to the script object. So I created a form variable (aka global variable) to contain the initial data. In each exit event I added a call to a function called checkData() which validates the value entered (either selected from the dropdown or a custom text entry) does not exist.

I am adding new values to the form variable and recreating the array from the form variable.This works fine for this use case but I would discourage adopting this for a form with many dropdowns and/or a lot of data bound to each dropdpown. You should really be using data binding and putting the processing on the server.

// form1.page1.subform1.dropdown1::exit - (JavaScript, client)

if (!form1.page1.subform1.dropdown1.isNull) {
    var str = form1.page1.subform1.dropdown1.rawValue;
    if (isNaN(str)) {
        populateDropDowns.checkData(this);
        form1.page1.subform1.dropdown2.clearItems();
        form1.page1.subform1.dropdown2.execInitialize();
    }
}

// form1.#variables[0].populateDropDowns - (JavaScript, client)

var stooge = new Array();

function loadData(dropdownField) {
    stooge = createArray();
    for (var i=0; i < stooge.length; i++) {
        dropdownField.addItem(stooge[i]);
    }
}

function checkData(dropdownField) {
    stooge = createArray();
    // check the value is not in the array
    if (stooge.lastIndexOf(dropdownField.rawValue) == -1) {
        addData(dropdownField);
    }   
}

function addData(dropdownField) {
    var stoogeStr_ = stoogeStr.value;
    // check the value is not in the global variable
    if (stoogeStr_.search(/dropdownField.rawValue/) == -1) {
        stoogeStr.value = stoogeStr.value + "," + dropdownField.rawValue;
        stooge = createArray();   
        stooge.push(dropdownField.rawValue);
        dropdownField.clearItems();
        loadData(dropdownField);
    }
}

function createArray() {
    var stoogeStr_ = stoogeStr.value;
    stooge = stoogeStr_.split(",");
    return stooge;
}

  • Because the initialise event repopulates the dropdown with the default Larry, Curly, Moe, the dropdown loses the "custom" entries on re-opening the PDF. Is there a way to save the final dropdown, so that the options are there when the file is saved, closed and re-opened?

This really requires a server-based solution or a rights-enabled form that allows client-side import/export of XML.

Steve

View solution in original post

14 Replies

Avatar

Former Community Member

Yes it is possible. First, on the dropdown list object Field tab you must enable "Allow Custom Text Entry". Second, add script to the exit event on the dropdown. Here are some example scripts:

1. The following script will add the text entered into the dropdown and the value binding for the value will be empty.

// form1.page1.subform1.dropdown::exit - (JavaScript, client)


form1.page1.subform1.dropdown.addItem(this.rawValue);

2. The following script will add the text entered into the dropdown and the value binding for the value will be the text.

// form1.page1.subform1.dropdown::exit - (JavaScript, client)


form1.page1.subform1.dropdown.addItem(this.rawValue,this.rawValue);

3. The following script will check the length of the existing dropdown, add the text entered into the dropdown, and add a binding for the value equal to the number of entries + 1. This example assumes the items in the list have value bindings equal to their index (where drop down list indexes are 1-based).

// form1.page1.subform1.dropdown::exit - (JavaScript, client)

var boundValue = form1.page1.subform1.dropdown.length + 1;
form1.page1.subform1.dropdown.addItem(this.rawValue,boundValue.toString());

Steve

Avatar

Former Community Member

?????

I can't get any of those to work. It doesn't come up with any errors or anything - it just doesn't add it to the drop down list. And yes, I have got allow custom text entry, exit event, Javascript, and client selected.

Also, can you have multiple drop-downs operating off the same list, or do they all have to have their own individual lists?

Thanks,

Josh

Avatar

Former Community Member

Check if your dropdown located within subform called "subform1" and it's name is "dropdown", corect the script  if needed.

Yan.

Avatar

Former Community Member

I have attached the sample PDF. If it gets queued and you need the sample immediately, please send me a private message on the forum or send a request to stwalker.adobe@gmail.com.

Additionally, you can have a single "list" attached to multiple drop-downs. There are different ways to achieve that objective. For a client-side solution you could create a global variable and parse the value to initialize each drop-down.

I want to point out that I amended the relevent script in the attached sample PDF. The isNaN() check is necessary to avoid re-adding values to the drop-down. You will need to take a look at the scripting guide if you don't understand binding.

http://livedocs.adobe.com/livecycle/8.2/acrobat_designer/wwhelp/wwhimpl/js/html/wwhelp.htm

// form1.page1.subform1.dropdown1::exit - (JavaScript, client)

if (!form1.page1.subform1.dropdown1.isNull) {
    var str = form1.page1.subform1.dropdown1.rawValue;
    if (isNaN(str)) {
        form1.page1.subform1.dropdown1.addItem(this.rawValue);
    }
}


// form1.page1.subform1.dropdown2::exit - (JavaScript, client)

if (!form1.page1.subform1.dropdown2.isNull) {
    var str = form1.page1.subform1.dropdown2.rawValue;
    if (isNaN(str)) {
        form1.page1.subform1.dropdown2.addItem(this.rawValue,this.rawValue);
    }
}


// form1.page1.subform1.dropdown3::exit - (JavaScript, client)

if (!form1.page1.subform1.dropdown3.isNull) {
    var str = form1.page1.subform1.dropdown3.rawValue;
    if (isNaN(str)) {
        var boundValue = form1.page1.subform1.dropdown3.length + 1;
        form1.page1.subform1.dropdown3.addItem(this.rawValue,boundValue.toString());
    }
}

Steve

Avatar

Former Community Member

Nup, still won't work.

I got the sample, but even when I re-type the whole lot in  again, it doesn't do anything.

Mine is in a table, but I've tried creating a new form exactly how you've done yours, and it still doesn't work. The only difference is that up the top of the Script Editor box, mine shows "form1.#subform[0].Subform1.dropdown1::exit - (JavaScript, client)", whereas yours comes up with "form1.page1.subform1.dropdown1::exit - (JavaScript, client)". I'm not sure how to change this.

This is what I have for dropdown3 (which is what I intend to use):

// Subform1.dropdown3::exit - (JavaScript, client)

if (!Subform1.dropdown3.isNull) {
    var str = Subform1.dropdown3.rawValue;
    if (isNaN(str)) {
        var boundValue = Subform1.dropdown3.length + 1;
        Subform1.dropdown3.addItem(this.rawValue,boundValue.toString());
    }
}

Avatar

Former Community Member

You have to change either he page subform name or change the script to reference 'form1.#subform[0].Subform1.dropdown1'.

I use the naming convention 'form1.page1.subform1.dropdown1.' In your case, 'page1' is the unnamed subform '#subform[0]'.

To change the subform name, go to the Hiearchy view, right-click on '#subform[0]', and select Rename. Alternatively, put focus on '#subform[0]', click F2, and change the name.

If you use the full path name to the field level in JavaScript or FormCalc, the path must match exactly.

Avatar

Former Community Member

Right, got that working now. Thanks for that - as you will have noticed, I am definitely a beginner at this.

Can someone please explain this in beginner terms for me? Using my limited knowlege, I have created a variable called Dropdown, and in the values section I have a list of the items. Is this what I should do?

I'm not sure how parsing works, so in the initialise event I just put $ = Dropdown. However, this does not give the desired effect of using this list in the dropdown list - instead, it just loads them all as shown.

Any input would be much appreciated.

Josh

Avatar

Former Community Member

Hey Josh,

Here is my approach.

1) Create a script object that

     a. contains a variable of type "Array" and initialize the array

     b. contains a function to populate a dropdown

2) In the initialize event of each dropdown, call the script object.

Here's what my script object looks like...

// form1.#variables[0].populateDropDowns - (JavaScript, client)

var stooge = new Array("","Larry","Curly","Moe");

function loadData(dropdownField) {
     for (var i=0; i < stooge.length; i++) {
         dropdownField.addItem(stooge[i]);
     }
}

I have three dropdowns so the initialize event for each dropdown contains:

// form1.page1.subform1.dropdown1::initialize - (JavaScript, client)

populateDropDowns.loadData(this);

// form1.page1.subform1.dropdown2::initialize - (JavaScript, client)

populateDropDowns.loadData(this);

// form1.page1.subform1.dropdown3::initialize - (JavaScript, client)

populateDropDowns.loadData(this);

Steve

Avatar

Former Community Member

Hello Steve,

Thanks for the reply, but unfortunately that is not doing what I want it to do.

I have a form with multiple drop-downs in a table, which all have the same list of items.

This is the effect I want:

When someone enters something (into any dropdown) that's not in the list, it gets added onto the list of every dropdown on the form.

The form you attached does not seem to do this - it only adds a new item to the drop-down into which you entered it. How did you get yours to display the list of items without anything in the "list items" box? when I take out my list items, the box won't drop down with all the options in preview mode. I have created the script object, but even when I create a new form to try to duplicate yours, I can't get it to add the items specified in the array to the list - it just doesn't drop down.

Thanks again, and sorry to be such a pain,

Josh

Avatar

Former Community Member

Josh, the whole point of this forum is pain relief. I think I understand your requirement now.

You asked, 'How did you get yours to display the list of items without anything in the "list items" box?'. The initialize event of each dropdown calls a function in the script object to load an array into the dropdown.

Here's what I have:

1)  dropdown1 initialize event calls loadData() in the script object populateDropDowns passing the dropdown1 object (reference this)

// form1.page1.subform1.dropdown1::initialize - (JavaScript, client)

populateDropDowns.loadData(this);

2) dropdown1 exit event checks to see if a user entered a value into the dropdown, checks to see if the value is alpha (JavaScript is Not a Number  function isNaN), calls addData() in the script object populateDropDowns passing the dropdown1 object (reference this), removes the items bound to to dropdown2 (clearItems()), and call execInitialize() on dropdown2 which results in binding the updated array to the dropdown

// form1.page1.subform1.dropdown1::exit - (JavaScript, client)

if (!form1.page1.subform1.dropdown1.isNull) {
    var str = form1.page1.subform1.dropdown1.rawValue;
    if (isNaN(str)) {
        populateDropDowns.addData(this);
        form1.page1.subform1.dropdown2.clearItems();
        form1.page1.subform1.dropdown2.execInitialize();
    }
}

Steps 1) and 2) are the same for dropdown2 with the applicable references to dropdown1.

Here's the script object:

// form1.#variables[0].populateDropDowns - (JavaScript, client)

var stooge = new Array("","Curly","Larry","Moe");

function loadData(dropdownField) {
    for (var i=0; i < stooge.length; i++) {
        dropdownField.addItem(stooge[i]);
    }
}

function addData(dropdownField) {
    stooge.sort();
    if (stooge.lastIndexOf(dropdownField.rawValue) == -1) {
        stooge.push(dropdownField.rawValue);
        dropdownField.clearItems();
        loadData(dropdownField);
    }
}

The addData() function should eliminate duplicates from being entered into the dropdown. It does a sort of the array and then uses the JavaScript function lastIndexOf() to verify that the value added to the dropdown is not already in the array. A -1 returned from the function indicates the new value was not found in the array. If the new value is not found, it is pushed (added) onto the array, the existing values are removed from the dropdown, and the loadData() function is called to bind the updated array to the dropdown.

Whew. Give it a go (do some testing for me) and let me know the results.

Steve

Avatar

Level 10

Hi Steve,

Excellent work!!

I have been following this with great interest, as we have been trying to implement this on a form. We were following your process, but could not implement it as seamlessly as typing into the dropdown list.

We generated a seperate textfield that on exit added the name to the list.

Your solution is great, but we are having difficulty extending it to our situation. I would be interested to have your views on the following:

  • The script adds one "custom" name. Subsequent names overwrite the original. Is it possible to have the ability to add an unlimited number of additional items to the dropdown?
  • Because the initialise event repopulates the dropdown with the default Larry, Curly, Moe, the dropdown loses the "custom" entries on re-opening the PDF. Is there a way to save the final dropdown, so that the options are there when the file is saved, closed and re-opened?

I was thinking that if  the current items were saved out of the script and then the initialise event called this instead of the array of default items.

There are going to be a lot of forms out there in the big bad world with variable "stooge

Thanks,

Niall

Avatar

Correct answer by
Former Community Member
  • The script adds one "custom" name. Subsequent names overwrite the original. Is it possible to have the ability to add an unlimited number of additional items to the dropdown?

OK and think v1.1 solves this problem. Testing, sorry, more testing may prove me wrong. The array has to be initialized in the body of a function, otherwise it gets created anew on each call to the script object. So I created a form variable (aka global variable) to contain the initial data. In each exit event I added a call to a function called checkData() which validates the value entered (either selected from the dropdown or a custom text entry) does not exist.

I am adding new values to the form variable and recreating the array from the form variable.This works fine for this use case but I would discourage adopting this for a form with many dropdowns and/or a lot of data bound to each dropdpown. You should really be using data binding and putting the processing on the server.

// form1.page1.subform1.dropdown1::exit - (JavaScript, client)

if (!form1.page1.subform1.dropdown1.isNull) {
    var str = form1.page1.subform1.dropdown1.rawValue;
    if (isNaN(str)) {
        populateDropDowns.checkData(this);
        form1.page1.subform1.dropdown2.clearItems();
        form1.page1.subform1.dropdown2.execInitialize();
    }
}

// form1.#variables[0].populateDropDowns - (JavaScript, client)

var stooge = new Array();

function loadData(dropdownField) {
    stooge = createArray();
    for (var i=0; i < stooge.length; i++) {
        dropdownField.addItem(stooge[i]);
    }
}

function checkData(dropdownField) {
    stooge = createArray();
    // check the value is not in the array
    if (stooge.lastIndexOf(dropdownField.rawValue) == -1) {
        addData(dropdownField);
    }   
}

function addData(dropdownField) {
    var stoogeStr_ = stoogeStr.value;
    // check the value is not in the global variable
    if (stoogeStr_.search(/dropdownField.rawValue/) == -1) {
        stoogeStr.value = stoogeStr.value + "," + dropdownField.rawValue;
        stooge = createArray();   
        stooge.push(dropdownField.rawValue);
        dropdownField.clearItems();
        loadData(dropdownField);
    }
}

function createArray() {
    var stoogeStr_ = stoogeStr.value;
    stooge = stoogeStr_.split(",");
    return stooge;
}

  • Because the initialise event repopulates the dropdown with the default Larry, Curly, Moe, the dropdown loses the "custom" entries on re-opening the PDF. Is there a way to save the final dropdown, so that the options are there when the file is saved, closed and re-opened?

This really requires a server-based solution or a rights-enabled form that allows client-side import/export of XML.

Steve

Avatar

Level 10

Thanks Steve,

Excellent, works a treat!

I am going to look into the server side solution. The form does not need to be reader enabled, so we should be able to get it working. Your sample is a great starting point.

Thanks,

Niall

Avatar

Former Community Member

Hello again,

I've finally got it working!! My script object had a spelling mistake in it, which was ruining everything, but now I'm away again, until I hit the next obstacle.

You'll hear from me soon...

Thanks very much for your patience,

Josh.

The following has evaluated to null or missing: ==> liqladmin("SELECT id, value FROM metrics WHERE id = 'net_accepted_solutions' and user.id = '${acceptedAnswer.author.id}'").data.items [in template "analytics-container" at line 83, column 41] ---- Tip: It's the step after the last dot that caused this error, not those before it. ---- Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: #assign answerAuthorNetSolutions = li... [in template "analytics-container" at line 83, column 5] ----