Как вызвать метод поддержки JSF, используя javascript, только когда страница загружена - PullRequest
0 голосов
/ 16 мая 2019

Проблема в том, что метод Back Bean вызывается много раз

хорошо, я уже прочитал этот ответ @BalusC

JSF - это язык на стороне сервера, который работает на веб-серверепо запросу HTTP и создает код HTML / CSS / JS, который возвращается с ответом HTTP.Все выражения EL в форме $ {} и # {} будут выполняться на стороне сервера во время генерации вывода HTML.JavaScript - это клиентский язык, который работает в веб-браузере и работает в дереве HTML DOM.Атрибут HTML onclick должен определять функцию JavaScript, которая будет выполняться на стороне клиента в конкретном событии HTML DOM.

Как вызывать метод вспомогательного компонента JSF, только когда onclick / oncomplete / on... происходит событие, а не при загрузке страницы

, поэтому я понимаю, почему метод моей спины был вызван много раз, так как я могу решить эту проблему

Это моя спинабыл метод

@ManagedBean (name="villeBean)"
@ViewScoped
public class Villes {
 public String listeVilles{
   return dao.listeVilles();
 }
}

и это мой код JS

if(localStorage['ville'] == null || localStorage['date']==null){
        localStorage.setItem('date',new Date());
        localStorage.setItem('ville',#{villeBean.listeVilles()});
}
else{ 
  var oldDate = new Date(localStorage['date']).getTime();;
  var currentDate = new Date().getTime();
  var distance =  currentDate - oldDate ;
  var days = Math.floor(distance / (1000 * 60 * 60 * 24));
  if (days >= 15){
    localStorage.setItem('date',date);
    localStorage.setItem('ville',#{villeBean.listeVilles()});
  }
} 

Проблема в том, что метод назад был вызван 2 раза

Ответы [ 3 ]

1 голос
/ 16 мая 2019

Для этого можно использовать компонент выходного сценария backbean jsf, если вы используете jsf EL внутри кода javascript, что обычно вызывает проблемы с несколькими запросами, поскольку один является статическим, а другой - динамическим.

Вы можете поместить этот код javascript в один файл js как функцию в папке вашего ресурса / js и вызывать эту функцию с помощью управляемого компонента:

    UIOutput output = new UIOutput();       
    output.setRendererType("javax.faces.resource.Script");

    // JS FILE NAME DEFINED IN resource/js folder is put here ( example: myscript.js):
    output.getAttributes().put("name", "myscript.js");
    output.getAttributes().put("library", "js");        
    facesContext.getViewRoot().addComponentResource(facesContext, output, "form");

    UIOutput script = (UIOutput) facesContext.getApplication()
            .createComponent(facesContext,
                    JAVAX_FACES_OUTPUT_COMPONENT_TYPE,
                    JAVAX_FACES_TEXT_RENDERER_TYPE);

    UIOutput outputScript = (UIOutput) facesContext.getApplication()
            .createComponent(facesContext,
                    JAVAX_FACES_OUTPUT_COMPONENT_TYPE,
                    DEFAULT_SCRIPT_RENDERER_TYPE);

    /** AT HERE YOU SHOULD CALL YOUR JAVA SCRIPT FUNCTION WITH THE PARAMETERS OF YOUR BACK BEAN

 let's say that you have created something like that:

function addToLocalStorage(ville){
if(localStorage['ville'] == null || localStorage['date']==null){
        localStorage.setItem('date',new Date());
        localStorage.setItem('ville',ville});
}
}

  So you're going to call the function from backbean like that:
*/

    String ville = villeBean.listeVilles();
    script.setValue("addToLocalStorage(" + ville + ")");

    script.setTransient(true);

    script.setId(facesContext.getViewRoot().createUniqueId());

    outputScript.getChildren().add(script);

    outputScript.setTransient(true);
    outputScript.setId(facesContext.getViewRoot().createUniqueId());

    facesContext.getViewRoot().addComponentResource(facesContext,
            outputScript, TARGET_ATTR);

Другой вариант - использовать RequestContext из пакета Primefaces, чтобы вы могли вызывать функции javascript из управляемых компонентов JSF:

RequestContext.getCurrentInstance().execute("myfunction()");
0 голосов
/ 16 мая 2019

Как выяснилось, вы действительно хотите иметь кэш на стороне клиента в localStorage и предотвращать вызов бизнес-логики, если этот кэш на стороне клиента действителен, вы должны пойти по AJAX-пути:

Я предлагаю реализоватьjavascript , отображаемый условно , который обновляет локальное хранилище только при необходимости:

<h:panelGroup id="updateLocalStorageScript" style="display: none;">
    <h:outputScript rendered="#{villeBean.updateLocalStorage}">
        localStorage.setItem('date',date);
        localStorage.setItem('ville', #{villeBean.villesList});
    </h:outputScript>
</h:panelGroup>

Обновление может быть инициировано действием команды, как предложено здесь: Как вызвать управляемую JSFbean для события HTML DOM с использованием собственного JavaScript?

<h:form id="frmHidden" style="display: none;">
    <h:commandButton id="cmdDoUpdateLocalStorage" action="#{villeBean.doUpdateLocalStorage()}">
        <f:ajax execute="@this" render=":updateLocalStorageScript" />
    </h:commandButton>
</h:form>

Конечно, вы также можете использовать p:remoteCommand, решение OmniFaces или другие предложения, предложенные в предыдущем QA.

ThisДействие команды приводит к визуализации JavaScript и инициализирует значение списка, вызывая вашу бизнес-логику только один раз.

@ManagedBean (name="villeBean)"
@ViewScoped
public class Villes {
    private boolean updateLocalStorage;

    private String villesList;

    public void doUpdateLocalStorage() {
        updateLocalStorage = true;
        villesList = dao.listeVilles();
    }

    public boolean isUpdateLocalStorage() {
        return updateLocalStorage;
    }

    public String getVillesList() {
        return villesList;
    }

}

Запустите эту команду из ваших условных блоков JavaScript:

if(localStorage['ville'] == null || localStorage['date']==null){
    document.getElementById('frmHidden:cmdDoUpdateLocalStorage').onclick();
}
else{ 
  var oldDate = new Date(localStorage['date']).getTime();;
  var currentDate = new Date().getTime();
  var distance =  currentDate - oldDate ;
  var days = Math.floor(distance / (1000 * 60 * 60 * 24));
  if (days >= 15){
    document.getElementById('frmHidden:cmdDoUpdateLocalStorage').onclick();
  }
} 
0 голосов
/ 16 мая 2019

У вас есть два экземпляра вашего EL-выражения #{villeBean.listeVilles()} в вашем javascript, который отображается (и, следовательно, вызывается) на стороне сервера, независимо от вашего состояния javascript.

Измените ваш скрипт так, чтобы он вызывался только один раз:

var villesList = #{villeBean.listeVilles()};
if(localStorage['ville'] == null || localStorage['date']==null){
        localStorage.setItem('date',new Date());
        localStorage.setItem('ville', villesList);
}
else{ 
  var oldDate = new Date(localStorage['date']).getTime();;
  var currentDate = new Date().getTime();
  var distance =  currentDate - oldDate ;
  var days = Math.floor(distance / (1000 * 60 * 60 * 24));
  if (days >= 15){
    localStorage.setItem('date',date);
    localStorage.setItem('ville', villesList);
  }
} 

Преимущество:

  • Бизнес-логика (dao.listeVilles()) вызывается только один раз (но это не гарантируется ...)
  • Потенциально огромный список отправляется в браузер только один раз, что снижает накладные расходы при передаче данных.

Тем не менее, лучше следовать советам Рикардо и Хольгера из ответа на Почему JSF несколько раз вызывает геттеры , предлагая изменить свой бин на:

@ManagedBean (name="villeBean")
@ViewScoped
public class Villes {

   private String villesList;

   public String listeVilles{
       if(villesList == null) {
           villesList = dao.listeVilles();
       }
       return villesList;
   }
}

Преимущество:

  • Бизнес-логика (dao.listeVilles()) вызывается только один раз для произвольного числа вхождений #{villeBean.listeVilles()} в вашем файле xhtml.

Риски:

  • Каждое вхождение #{villeBean.listeVilles()} в вашем xhtml по-прежнему отображает и передает потенциально огромный список.
  • Ваше представление может видеть старые / устаревшие данные при работе с AJAX, поскольку этот кэш никогда не аннулируется в одной и той же области видимости.
...