События изменения аргументов шаблона

Помимо возможности ссылочности, чтения и записи данных, функционал аргументов шаблона поддерживает возможность мониторинга изменения состояния аргумента. Это реализовывается через методы onArg и onArg[ARG_NAME] объекта враппера. При каждом изменении аргумента шаблона методом setArg выполняется вызов методов fcf.NClient.Wrapper.onArg и fcf.NClient.Wrapper.onArg[ARG_NAME], которые могут быть определены в классе враппера и выступать в качестве наблюдателя состояния изменения аргумента.

Метод fcf.NClient.Wrapper.onArg

Метод fcf.NClient.Wrapper.onArg вызывается при каждом изменении аргумента шаблона.

Метод имеет следующую сигнатуру:

onArg(string a_argName, mixed a_value, fcf.NClient.Wrapper a_editor, bool a_ignoreRedrawing, bool a_isInnerCall, string a_suffix)

Аргументы:

  • string a_argName - Имя аргумента.
  • mixed a_value - Новое устанавливаемое значение.
  • fcf.NClient.Wrapper a_editor - Объект на котором был вызван метод setArg. При применении ссылок a_editor и this могут быть не равны
  • bool a_ignoreRedrawing - Флаг запрещающий перерисовку. Устанавливается методом setArg.
  • bool a_innerCall - Флаг внутреннего вызова из самого шаблона, используется для построения логики внутренней обработки. Устанавливается методом setArg.
  • string a_suffix - Путь изменяемого значения в аргументе.

Метод fcf.NClient.Wrapper.onArg[ARG_NAME]

В отличие от метода fcf.NClient.Wrapper.onArg метод fcf.NClient.Wrapper.onArg[ARG_NAME] вызывается при каждом изменении конкретного аргумента шаблона. Полное имя метода формируется из префикса onArg и суффикса ARG_NAME. Суффикс является именем аргумента шаблона начинающимся с большой буквы.

Метод имеет следующую сигнатуру:

onArg[ARG_NAME](mixed a_value, fcf.NClient.Wrappera_editor, bool a_ignoreRedrawing, bool a_isInnerCall, string a_suffix)

Аргументы:

  • mixed a_value - Новое устанавливаемое значение.
  • fcf.NClient.Wrapper a_editor - Объект на котором был вызван метод setArg. При применении ссылок a_editor и this могут быть не равны
  • bool a_ignoreRedrawing - Флаг запрещающий перерисовку. Устанавливается методом setArg.
  • bool a_innerCall - Флаг внутреннего вызова из самого шаблона, используется для построения логики внутренней обработки. Устанавливается методом setArg.
  • string a_suffix - Путь изменяемого значения в аргументе.

Практическое применение метода fcf.NClient.Wrapper.onArg

Добавим к нашему приложению смену состояния аргумента "enable" для кнопки "Save". Данный аргумент отвечает за активность кнопки. Если аргументы шаблона не были изменены, состояние "enable" будет false, а при первом редактировании конфигурации оно будет меняться на true.

Это мы будем реализовывать при помощи метода onArg. Возможность отслеживания изменения аргумента шаблона дает более высокую гибкость разработки. Именно для этой задачи данная методика подходит лучше всего. Так так, снимает с программиста задачу отслеживать изменение аргументов или создавать наборы отдельных функций для установки значений.

Приступим. В аргументе _modify мы будем хранить состояние изменения аргументов, данный аргумент будет передан в шаблон кнопки "Save" по ссылке в виде аргумента "enable".

Файл :templates/blocks/moving-containers.tmpl

... //~ARGUMENTS { _strings: fcf.argProg(), _file: fcf.argVal("/files/background.jpg?dump=@{{fcf.id()}}@"),
_reboundCounter: 0, _modify: false } //~TEMPLATE <div class="moving-containers-view" style="background-image: url(@{{args._file}}@);"> <div class="moving-containers-view-info"> Rebound counter: <span name="rebound_counter">#{{args._reboundCounter}}#</span> </div> %{{ for(let i = 0; i < args._strings.length; ++i) { }}% @{{ render.template( "+view-item", { string: fcf.argRef(`_strings[${i}]`), fcfEventRebound: "parent.onReboundString(event)" })}}@ %{{ } }}% </div> <fieldset> <legend>Editor</legend> @{{ render.template("@controls:tabs", { items: fcf.argVal({ strings: { title: "Strings", data: fcf.argTmpl("+strings", {strings: fcf.argRef("_strings")}) }, settings: { title: "Settings", data: fcf.argTmpl("+settings") } }) }); }}@ @{{ render.template("@controls:button", {title: fcf.t("Save"), enable: fcf.argRef("_modify"), fcfEventClick: "parent.onSave()"}); }}@ ...

И добавим работу с аргументом _modify в файл враппера

Файл :templates/blocks/moving-containers.wrapper.js

fcf.module({ name: "templates/blocks/moving-containers.wrapper.js", dependencies: ["fcf:NClient/Wrapper.js"], module: function(Wrapper){ return class WrapperImpl extends Wrapper{ constructor(a_initializeOptions) { super(a_initializeOptions); } onArg(a_argName, a_value, a_editor, a_ignoreRedrawing, a_isInnerCall, a_suffix) { if ((a_argName == "_strings" || a_argName == "_file") && !this.getArg("_modify")) { this.setArg("_modify", true); } } onRemoveString(a_index) { let strings = this.getArg("_strings"); strings.splice(a_index, 1); this.setArg("_strings", strings); this.update(); } onAddString() { let strings = this.getArg("_strings"); strings.push("") this.setArg("_strings", strings); this.update(); } onFile() { let self = this; let fileReader = new FileReader(); fileReader.onload = () => { self.setArg("_file", fileReader.result); self.update(); } fileReader.readAsDataURL(this.select("input[type=file]")[0].files[0]); } onSave() { this.send({strings: this.getArg("_strings")}, [this.select("input[type='file']")[0]]); this.setArg("_modify", false); } }; } });

Как видно код функционала занимает всего несколько строчек. Теперь посмотрим на результат.