Smalltalk Seaside — обратный вызов jQuery Ajax

Итак, у меня есть обратный вызов без Ajax, отлично работающий с использованием этого кода (метод «convert» вычисляет новое значение для переменной экземпляра «result»):

        html form: [
        html text: 'Number to convert: '.
        html textInput
            callback: [ :value | self setNumtoconvert: value ];
            value: numtoconvert.
        html break.
        html text: 'Result: '.
        html text: result.
        html break.
        html submitButton
            value: 'Convert';
            callback: [ self convert ]
    ].

... и теперь я пытаюсь "Ajax-ify" с помощью jQuery. Я пробовал что-то в этом роде:

(html button)
    onClick: ((html jQuery ajax)
        callback: [ self convert]);
    id: 'calclink';
    with: 'Convert'.

...что не работает, так как я явно упускаю какой-то секретный соус. Может ли эксперт Seaside присоединиться и дать мне краткое руководство по преобразованию «обычного» кода обратного вызова в код обратного вызова «jQuery Ajax»?

ОБНОВЛЕНИЕ Я очень близок к тому, чтобы понять это; После поиска в Интернете и повторного просмотра черновиков глав в книге Seaside я изменил свою кнопку Ajax-ified на это:

(html button)
    onClick: ((html jQuery ajax)
        callback:[:val | self setNumtoconvert: val.
            self convert.
            Transcript show: self getResult.]
            value:(html jQuery: '#txtNumToConvert') value;
        onComplete: ((html jQuery: '#txtResult') value: self getResult)
        );
    id: 'calclink';
    with: 'Convert'.

Теперь единственный вопрос заключается в том, как установить значение текстового поля «#txtResult»; Transcript show: self getResult отображает правильное значение, но я не могу заставить строку «onComplete» обновить значение «#txtResult». Я могу использовать onComplete: ((html jQuery: '#txtResult') value: 'hello there') для вставки строковой константы в текстовое поле, но self getResult не предоставляет значение для текстового поля, хотя, опять же, я получаю правильное значение при отображении self getResult в окне стенограммы.

ОБНОВЛЕНИЕ ВТОРОЕ Моя строка onComplete действительно работает, но только после нажатия кнопки (для вычисления значения), обновления страницы, затем нажатия кнопку еще раз (чтобы отобразить рассчитанное значение в текстовом поле «txtResult». Как это исправить?

МОЙ ОТВЕТ

Наконец-то я придумал решение, которое легче понять (для меня) и менее многословно, что мне очень нравится:

renderContentOn: html
html form:[     
    html textInput
       id: #txtNumToConvert;
       callback: [ :value | self setNumtoconvert: value ];
       value: numtoconvert.
    html break.
    html span
       id: #result;
       with: result.
  html break.
  html anchor
     url: 'javascript:void(0)';
     onClick: ((html jQuery id: #result) load
       serializeForm;
       html: [self convert. html span with: result]);
     with: 'Convert to Decimal'.
 ]

person Bryan Green    schedule 20.04.2015    source источник
comment
Можете ли вы описать немного больше, что «не работает»?   -  person Johan B    schedule 20.04.2015
comment
Что ж, текстовое поле «результат» не обновляется результатом присвоения нового значения переменной экземпляра класса «результат». Когда я нажимаю кнопку "jQuery", я вижу, что вызов Ajax запускается (с использованием Firebug), но на самом деле ничего не происходит....   -  person Bryan Green    schedule 20.04.2015


Ответы (2)


Во-первых, вам также нужно активировать обратные вызовы для полей внутри формы. Следующий код прикрепляет обработчик события щелчка к кнопке, которая выполняет запрос ajax, который сериализует всю форму, а затем выполняет обратный вызов кнопки.

(html button)
   onClick: ((html jQuery ajax)
       serializeForm;
       callback: [ self convert ]);
   id: 'calclink';
   with: 'Convert'.

Когда вы используете обычную отправку формы, Seaside инициирует обратные вызовы для всех полей внутри формы. Если вы хотите инициировать отправку формы как запрос ajax, метод #serializeForm Seaside-jQuery также сериализует содержимое всех полей ввода внутри формы и запускает их обратные вызовы на стороне сервера в запросе ajax, как и в «стандартном». ' подача формы. Не нужно менять реализацию формы!

Затем вы захотите подавить поведение браузера по умолчанию, когда вы нажимаете кнопку отправки, которая отправляет форму в запросе POST и заставляет браузер делать запрос на всю страницу, что заставит Seaside (повторно) отображать страницу. Есть несколько способов сделать это, но проще всего просто изменить тип кнопки:

(html button)
   bePush;
  ...

Наконец, вам нужно обновить содержимое страницы. Вы используете #onComplete: правильно, за исключением того, что этот код javascript генерируется при первом отображении страницы. Следовательно, он отображает значение self getResult в момент отображения страницы. Вам нужно значение после отправки формы. Для этого требуется еще один обратный вызов:

(html button)
   bePush;
   onClick: ((html jQuery ajax)
       serializeForm;
       callback: [ self convert ];
       onComplete: ((html jQuery: '#txtResult') load html: [:r | self renderTextResultContentsOn: r]));
   id: 'calclink';
   with: 'Convert'.

ОБНОВЛЕНИЕ Приведенный выше код выполняет два обращения к серверу, которые можно оптимизировать, объединив обратные вызовы в один запрос ajax:

(html button)
   bePush;
   onClick: ((html jQuery ajax)
       serializeForm;
       script: [:s | self convert. s << ((s jQuery: '#txtResult') html: [:r | self renderTextResultContentsOn: r])]);
   id: 'calclink';
   with: 'Convert'.

Или, более элегантно:

    (html button)
       bePush;
       onClick: ((html jQuery id: #count) load
                    serializeForm;
                    html: [:r | self convert. self renderTextResultContentsOn: r]);
       with: 'Convert'.

Приведенный выше код генерирует запрос ajax, который выполняет сериализацию формы (выполнение обратных вызовов на стороне сервера) и генерирует сценарий для изменения результата на странице. Причина, по которой я поместил self convert внутри обратного вызова сценария, заключается в том, что вы можете указать только один обратный вызов «генерация ответа» на каждый запрос ajax (например, только один обратный вызов script, html, json на запрос). Это логическое ограничение, поскольку один запрос может генерировать только один ответ. Однако вы можете добавить несколько «вторичных» обратных вызовов (например, обратные вызовы сериализации формы, callback:json: и т. д.), но обратный вызов, указанный с использованием #callback:, также является основным обратным вызовом в коде Seaside. Следовательно, мне нужно было поместить self convert внутри обратного вызова сценария, а не в его собственном блоке обратного вызова.

person Johan B    schedule 21.04.2015
comment
Так зачем же нужны два обращения к серверу туда и обратно, если при использовании прямого Javascript требуется только одно обращение? - person Bryan Green; 22.04.2015
comment
В вашем коде значение, которое отображается, — это не значение, которое вы только что ввели, а значение, которое присутствовало при создании скрипта. Вы можете избежать двух круговых поездок, комбинируя обратные вызовы в запросе ajax, но я обновлю свой ответ, чтобы показать это. - person Johan B; 22.04.2015
comment
Спасибо за помощь, Йохан! - person Bryan Green; 22.04.2015

«Ничего не происходит», потому что все, что вы делаете, это отправляете запрос AJAX к изображению. Однако вам кажется, что вы хотите инициировать обновление узла DOM. Для этого требуется запрос AJAX с дополнительным обработчиком, который обновляет элемент DOM с результатом некоторого рендеринга.

То, что вам не хватает на стороне изображения, в основном:

  • каков идентификатор элемента, который вы хотите обновить?
  • какой код рендеринга должен быть выполнен для генерации HTML для замены?

Я не использую jQuery, но, глядя на код Seaside jQuery, я думаю, что ваш фрагмент должен выглядеть примерно так:

(html button)
  onClick: (html jQuery ajax
    "pass the id of the element to update"
    id: 'calclink';
    callback: [ self convert];
    "specify the method to call for rendering"
    html: [ :canvas | self basicRenderMyDivOn: canvas ];
    yourself);
  id: 'calclink';
  with: 'Convert'.
person Max Leske    schedule 21.04.2015