0

I want to pass a list of objects (list_A in the example), in a jsf file, to a function in javascript. The problem is that the call event.name="#{controllerManagedBean.list_A.get(y).getName()}"; assigns to event.name the value as if the "y" always had a value of 0, that is, the first item in the list.

How can I go through the list and pass all the names to list_1 (without a json, if possible)?

Thanks!!

Here is my code (the important thing is the script, I think):

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <script src="visJS/dist/vis.js"></script>
        <link href="visJS/dist/vis-timeline-graph2d.min.css" rel="stylesheet" type="text/css" />
    </h:head>
    <h:body>
        <h:form>
            <h:dataTable value="#{controllerManagedBean.list_A}"
            var="evento" border="2"
            cellspacing="1" cellpadding="1">
                <h:column>
                    <f:facet name="header">Evento</f:facet>
                    #{evento.nombre}
                </h:column>
            </h:dataTable>
        </h:form>
        <div id="timeline">Prueba</div>

        <script src="js/timeline.js"></script>
        <script>
          var x = parseInt('#{controllerManagedBean.list_A.size()}');
          var list_1 = new Array();

          //<![CDATA[
              for(var y = 0; y<x; y++){
          //]]>
                  var evento = new Object();
                      evento.nombre = "#{controllerManagedBean.list_A.get(y).getNombre()}";
                      list_1.push(evento);
              }
          myFunction(list_1);
        </script>

    </h:body>
</html>
pgsanchez
  • 1
  • 2
  • 1
    see [this](https://stackoverflow.com/questions/14709014/how-do-i-pass-jsf-managed-bean-properties-to-a-javascript-function) question. You must convert it to a string in jsf and then in js convert it back. so using json, xml or custom conversion is the only possibility – fuggerjaki61 Feb 10 '20 at 11:47
  • @fuggerjaki61: No you don't. A ui:repeat can work as the link you referred to does not say to convert and convert back (See https://stackoverflow.com/questions/2547814). The problem was not passing things as a string (with single quotes around it) In this case OP is **thinking/assuming** the `"#{controllerManagedBean.list_A.get(y).getNombre()}"` is evaluated each time in the loop which it is not. It is evaluated once. OP can easilly build te required list with EL and javascript with the use of a ui:repeat as can be seen in the link in this comment and then iterate over that list. – Kukeltje Feb 10 '20 at 12:03
  • 1
    Does this answer your question? [Mixing JSF EL in a JavaScript file](https://stackoverflow.com/questions/2547814/mixing-jsf-el-in-a-javascript-file) – Kukeltje Feb 10 '20 at 12:04
  • Not yet, because the line , gives me an error: the prefix ui for the element ui:repeat is not linked. But I´m still trying...thanks! – pgsanchez Feb 10 '20 at 15:22
  • The reason for this 'new' error and the solution is easily found via a search engine. Just post the error verbatim in there. – Kukeltje Feb 10 '20 at 18:55
  • 1
    @pgsanchez To show you a little bit more the problem: The loop `for(var y = 0;` is executed in the browser. All EL expressions like `#{controllerManagedBean.list_A.get(y)` are executed at server side *before* the page is delivered to the browser. You see, `y` in this EL can't have a legal value. – Holger Feb 11 '20 at 07:58
  • Thank you very muchs @Holger. Your answer helped me to better understand the problem. I´m going to write an answer with my solution. – pgsanchez Feb 11 '20 at 15:17
  • You should give your variable names more meaning. Instead of list 1 ... 9, A ... Z better use speaking variables like `events` so the next programer, your supervisor and more important yourself after some time still knows what you are doing. `parseInt` is obsolete since `size()` is guaranteed to return an integer. – djmj Feb 26 '20 at 01:49
  • 1
    I know it, @djmj. In my code I use, as you said, variable names more meaning, but in spahish. So I though here it could be easier to name a list as list_1 instead of listaRepostajes. But thank you for your suggestion! – pgsanchez Feb 27 '20 at 07:38

2 Answers2

1

You can use json as @pgsanchez proposes in his answer but in your case you have a simple data stucture you can more easily create a javascript array like following:

<script>

    // fill javascript array with bean integer values using string joining
    var jsEventNumbers: [#{bean.events.stream().map(e -> e.number).reduce((p1, p2) -> p1 += ', ' += p2).get()}];

    myFunction(jsEventNumbers);

</script>

The json approach is more flexible though. You can also look here:

djmj
  • 5,579
  • 5
  • 54
  • 92
0

I've finally solved it as @fuggerjaki61 said, through a JSON

The @Kukeltje solution of using a ui: repeat did not work for me, because the ui: repeat cannot be put inside a script block. But thank you very much!

My solution is: In the server part (It is a web application) I put a function that goes through the list list_A and generates a JSON format string with all the data.

private String listInJSON;
public void convertToJson()
{
    Gson gson = new Gson();
    listInJSON = "";
    listInJSON += "[";
    for(MyObject obj: list_A){
        listInJSON += gson.toJson(obj);
        listInJSON += ",";
    }
    listInJSON += "]";
    listInJSON = listInJSON.replace("},]", "}]");
}

This generates a String with JSON format: [{...},{...},...{...}] e.g. In my case: [{"name":"Prueba","date":"Sep 10, 1999 12:00:00 AM"}, ...]

In my index.html, I call a javascript function procesarJSON:

onclick="procesarJSON('#{controllerManagedBean.listInJSON}')"

And finally, in my javascript file:

function procesarJSON(jsonCompleto){
    var obj = JSON.parse(jsonCompleto); 

    for (var i = 0; i < obj.length; i++)
    {
        console.log('name = ' + obj[i].name); // prints: Prueba
        // Remember the JSON: [{"name":"Prueba","date":"Sep 10, 1999 12:00:00 AM"}, ...]
        // To process the rest of the data here. 
    }

}

Thanks to all!!

pgsanchez
  • 1
  • 2
  • oh and why not create json from a list directly: https://stackoverflow.com/questions/14228912/how-to-convert-list-to-json-in-java/14229020 – Kukeltje Feb 11 '20 at 17:38