Сила JavaScript в том, что вы можете делать что угодно. Все, что вам нужно, это вариант использования.

Любопытный случай Javascript .apply() и Salesforce ActionFunction.

Лично мне всегда нравится работать с javascript. Больше я изучаю js, больше узнаю. И да, это всегда волнует меня. Это мотивирует меня постоянно учиться. На том же фронте я изучал динамические вызовы функций в JS. В Salesforce динамический вызов функции вообще непрост (единственный способ сделать это — использовать класс Type). Мы все знаем, что можем динамически вызывать функцию в JS, используя различные способы, такие как apply, bind, call. Изучая функцию .apply(), я начал изучать возможные варианты использования .apply(), так как я всегда верю в обучение на примере использования. Мы увидим, почему я изучал применение.

Кто плохо знаком с JS или вызовом динамических функций, позвольте мне дать краткий обзор. В JS мы можем создавать функции, функции — это строительные блоки, несущие ответственность. Ответственность за выполнение операций, получение информации и многое другое. Теперь предположим, что вы работаете с такой системой, как механизм правил, и вам нужно оценить, соответствует ли условие или нет, а затем вам нужно вызвать какую-то функцию. Для этого вы можете использовать call, apply или bind.

Используйте .bind(), если вы хотите, чтобы эта функция позже вызывалась с определенным контекстом, что очень полезно в событиях. Принимая во внимание, что .call() или .apply(), когда вы хотите немедленно вызвать функцию и изменить контекст. Call() вызывает функцию и позволяет передавать аргументы один за другим, тогда как Apply() вызывает функцию и позволяет передавать аргументы в виде массива. Здесь передача параметров в виде массива является ключевой, и именно по этой причине я исследовал .apply(). Поскольку я говорил об обучении с помощью приведенного ниже варианта использования, я выбрал вариант использования.

Функции действий Salesforce

В Salesforce функции действия используются для асинхронного вызова методов контроллера. Обычный поток будет

Создайте функцию действия, создайте функцию JS (которая извлекает значения, проверки), вызовите функцию JS, которая вызовет функцию действия.

Основным узким местом (для меня) при вызове функции действия из функций JS является передача параметров и проверок. О проверке можно легко позаботиться библиотекой JS, но для передачи параметра это не так. Кроме того, если страница VF в значительной степени управляется функцией действия, то в итоге вы написали так много функций JS. Это приводит к проблемам с читаемостью кода и ремонтопригодностью.

Как мы можем использовать Apply() для решения вышеуказанной проблемы?

Как я упоминал ранее, передача параметров в виде массива является ключевым моментом. Почему ? потому что для каждой функции действия количество необходимых параметров будет разным. Поэтому передача массива - хороший вариант.

Шаг 1 — Конфигурации

Теперь давайте посмотрим, часть конфигурации, здесь я использовал атрибуты данных Html-5 для хранения конфигурации. Если вы хотите сохранить какие-либо настраиваемые атрибуты и получить к ним довольно простой доступ, вы можете использовать атрибут data-*. Все, что вам нужно сделать, это определить название пользовательского атрибута данных на уровне элемента. И как получить к нему доступ, используя свойство ‹element›.dataset.‹attributename› . Посмотрим, как я его использовал. Я создал кнопки ввода, а для кнопок ввода я создал настраиваемый атрибут «data-actionfunction», в котором я сохраняю имя вызываемой функции действия. При вызове функции действия нам также необходимо передавать параметры, поэтому я создал еще один атрибут «data-parameter». Для уникальной идентификации кнопок с настроенной функцией действия у меня есть атрибут «data-action». Ниже приведен фрагмент того же самого.

<input id=”btnAction1" type=”button” data-action=”register” data-actionfunction=”act1" data-parameter=”#txt1" value=”Action1"/>

Шаг 2 — Регистрация на мероприятие.

Как видно из приведенного выше примера, я не добавлял никаких событий on-click. Так что я буду делать это на этом шаге. Теперь, используя атрибут «data-action», мы получим все кнопки, для которых настроена функция действия.

// retrieve all buttons
let domelements=_document.querySelectorAll(“input[data-action=’register’]”);
domElements.forEach(function(domElement,index){
    
    //get action function name using dataset. 
    let actionfunction=domElement.dataset.actionfunction;
    if(!!actionfunction){
       // register event.
       domElement.addEventListener(“click”,onclick,false);
    }
});

Шаг 3. Вызов ActionFunction

На шагах 1 и 2 мы завершили первоначальную настройку конфигурации и регистрацию событий. На этом шаге мы будем делать, извлекать значение элементов и вызывать функцию действия с параметрами. Для этого снова будет использоваться атрибут набора данных. Теперь всякий раз, когда кнопка будет нажата, мы получим экземпляр этой кнопки с помощью ключевого слова «this» и будем использовать его для извлечения атрибута.

const scope=this;
let actFunction=scope.dataset.actionfunction;
let parameters=scope.dataset.parameter;

Теперь, используя атрибут параметра, мы можем сделать запрос к элементу и получить его значение. Ниже приведен фрагмент того же.

function onclick(){
   const scope=this;
   //get action fucntion name
   let actFunction=scope.dataset.actionfunction;
   
   //get elements name, that values need to pass.
   let parameters=scope.dataset.parameter;
   let selectors=parameters.split(“,”);
   let values=[]; // values to be send, hold in this array.
   selectors.forEach(function(dom,index){
        var domEle=document.querySelector(dom);
        values.push(domEle.value);
   });
}

Теперь ключом для вызова функции действия является окнопеременная. Его глобальная переменная, представляющая окно, в котором выполняется скрипт, подвергается воздействию кода JavaScript. Таким образом, для вызова функции действия используется приведенный ниже код.

window[actFunction].apply(null,values);

Полный фрагмент кода-

function onclick(){
const scope=this;
//get action fucntion namelet actFunction=scope.dataset.actionfunction; 
//get elements name, that values need to pass.
let parameters=scope.dataset.parameter;
let selectors=parameters.split(“,”);
let values=[]; // values to be send, hold in this array
selectors.forEach(function(dom,index){
   var domEle=document.querySelector(dom);
   values.push(domEle.value);
});
  //as we don’t need to pass any context so first param is null.
  window[actFunction].apply(null,values);
}

Полный фрагмент

(function(_window,_document){
    let configuration={
       selector:"input[data-action='register']"
     }
     this.ActionWrapper=function(){
        console.log("Action Wrapper Initialized");
     }
     function onclick(){
       const scope=this;
       let actFunction=scope.dataset.actionfunction;
       let parameters=scope.dataset.parameter;         
       let selectors=parameters.split(",");
       let values=[];
       selectors.forEach(function(dom,index){
          var domEle=document.querySelector(dom);
          values.push(domEle.value);
       });                
       window[actFunction].apply(null,values);
     }
     
     this.ActionWrapper.prototype.config=configuration;
      
     this.ActionWrapper.prototype.Initialize=()=>{
       let eleSelector=configuration.selector;
       let eleCount=_document.querySelectorAll(eleSelector);
         SubscribeEvents(eleCount);
       }
     let SubscribeEvents=(domElements)=>{
         domElements.forEach(function(domElement,index){
            let actionfunction=domElement.dataset.actionfunction;
            if(!!actionfunction){
               domElement.addEventListener("click",onclick,false);
             }
          });
      }            
     _window.onload=function(){
           let wrapper=new ActionWrapper();
           wrapper.Initialize();
     }                
})(window,document);
//VF code 
<input id="btnAction1" type="button" data-action="register" data-actionfunction="act1" data-parameter="#txt1" value="Action1"/>
<!-- Action Function Starts-->
<apex:actionFunction name="act1" action="{!ActionCall}" reRender="dummy">
     <apex:param name="param1" assignTo="{!parameter1}" value=""/>
</apex:actionFunction>

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

Если у вас есть какие-либо комментарии или предложения, пожалуйста, дайте знать.