Jump to content

Программно заполнить unimDBLookupComboBox и выбрать значение


x11

Recommended Posts

На форме есть много списков типа TnimDBLookupComboBox. Все они работают в режиме RemoteQuery, т.е.:
 

RemoteQuery := True;

RemoteQueryRetainResult := True;

При загрузке формы нужно у некоторых списков указать значение по умолчанию, т.е. чтобы, когда форма откроется, у этих списков уже было что-то выбрано и заполнено поле KeyValue. Чтобы потом, это значение KeyValue считать при сохранении объекта в базу.

Как это правильно сделать?

Вот мой код (DoOnNewRecord вызывается в FormShow)

TStrIntPair = record
    key: integer;
    val: string;
  end;
...
...  
  
procedure TfmmForm1.DoOnNewRecord;
Var
  StrIntPair: TStrIntPair;
begin
// валюта по умолчанию
  StrIntPair := UniMainModule.GetDefaultCarrency;
  OutputDebugString(PWideChar(StrIntPair.val));

  if StrIntPair.key <> 0 then
  begin
    comboCurr.Items.Add(StrIntPair.val);
    comboCurr.KeyValue  := StrIntPair.key;
    comboCurr.Text      := StrIntPair.val;
    comboCurr.ItemIndex := 0;

  end;

end;

 

В отладчике вижу, что структура StrIntPair заполнена. Например, StrIntPair.key имеет значение 2.

Но после открытия формы список пустой и валюта не выбрана. На снимке видно, что ничего не выбрано, а слово "валюта" - это placeholder (EmptyText).

 

Screenshot_1.jpg

Link to comment
Share on other sites

Попробуйте этот код:

procedure TMainmForm.UnimFormReady(Sender: TObject);
var
  val: string;
begin
  val := '... Значение ...';
  with UnimDBLookupComboBox1.JSInterface do
  begin
    JSCode(#1'.store.add({"id":0, "val":"'+ val +'"});');
    JSCall('setValue', [val]);
  end;
end;

 

  • Like 1
Link to comment
Share on other sites

Ок, а как потом при чтении значения узнать KeyValue?

Ведь в таблицу не записывается UnimDBLookupComboBox1.Text,  а записывется UnimDBLookupComboBox1.KeyValue.

Link to comment
Share on other sites

Извините, всё равно не понял.

Согласно вашему коду, при старте формы я заполняю ТОЛЬКО свойство TEXT.

Потом, при закрытии формы, при сохранении данных в базу нужно откуда-то взять KeyValue. Как в данном случае использовать событии GetKeyValue? На момент закрытия формы KeyValue НИГДЕ нет.

Никаких датасетов к UnimDBLookupComboBox1 не привязано.

Link to comment
Share on other sites

1 minute ago, x11 said:

Извините, всё равно не понял.

OK.

Откройте пожалуйста демо пример:

\FMSoft\Framework\uniGUI\Demos\Touch\DBLookupComboBox - Custom Remote Query (CDS)

1. Вышеуказанный код:

procedure TMainmForm.UnimFormReady(Sender: TObject);
var
  val: string;
begin
  val := '10119, Domenick, Peltason';
  with UnimDBLookupComboBox1.JSInterface do
  begin
    JSCode(#1'.store.add({"id":0, "val":"'+ val +'"});');
    JSCall('setValue', [val]);
  end;
end;

2. Поставьте точку останова:

procedure TMainForm.UniDBLookupComboBox1GetKeyValue(const Value: string; var KeyValue: Variant);
var
  S : string;
  I : Integer;
begin
  S := Value;
  KeyValue := Null;
  if S <> '' then
  begin
    I := Pos(',', S);
    if I > 0 then
      S := Copy(S, 1, I - 1)
    else
      Exit;

    UniMainModule.ClientDataSet2.Filtered := False;
    UniMainModule.ClientDataSet2.SetKey;
    UniMainModule.ClientDataSet2.FieldByName('emp_no').AsString := S;
    if UniMainModule.ClientDataSet2.GotoKey then
      KeyValue := UniMainModule.ClientDataSet2.FieldByName('emp_no').Value;
  end;
end;

 

Link to comment
Share on other sites

Вот код при сохранении данных в базу:

 

qSave.FieldByName('ID_SERVICE').AsInteger             := comboServices.KeyValue;
qSave.FieldByName('ID_STATE').AsInteger               := comboState.KeyValue;
qSave.FieldByName('ID_CURRENCY').AsInteger            := comboCurr.KeyValue;

 

тут использовать событие UniDBLookupComboBox1GetKeyValue никак не получится

Link to comment
Share on other sites

В общем, как оказалось, даже у тех UniDBLookupComboBox, где значение выбрано пользователем, тоже NULL.

qFill - компонента TUniQuery. qFill лежит на форме одна и используется (открывается) на момент наполнения и выбора значения.

 

Вот так заполняю:

procedure TfmmForm1.comboCurrRemoteQuery(const QueryString: string;  Result: TStrings);
begin
  comboOnRemoteQuery(qFill, 'TCURRENCY', QueryString, Result);
end;

...
...
procedure comboOnRemoteQuery(q: TUniQuery; const sTable, QueryString: string; var Result: TStrings);
Var
 n: integer;
begin

  q.Close;
  q.SQL.Text := 'SELECT ID, NAME FROM ' + sTable + ' WHERE UPPER(NAME) CONTAINING(UPPER(:NAME)) AND DELETED IS DISTINCT FROM 1';

  if (QueryString.Length <= 2) and (QueryString <> '*') then
    exit;


  if (QueryString = '*') or (QueryString = '[null]') then
    q.Params[0].AsString := ''
  else
    q.Params[0].AsString := QueryString;

  q.Open;

  if q.RecordCount = 0 then
  begin
    Result.Add(constEmptyRes);// совпадений не найдено
    exit;
  end;

  n := 0;
  q.First;
  while not q.Eof do
  begin
    Result.AddPair(q.FieldByName('name').AsString, q.FieldByName('id').AsString);
    q.Next;

    inc(n);
    if N > 100 then Break;
  end;

end;

 

вот событие

procedure TfmmForm1.comboCurrGetKeyValue(const Value: string; var KeyValue: Variant);
begin
  comboOnGetKeyValue(qFill, Value, KeyValue);
end;

...
...

procedure comboOnGetKeyValue(q: TUniQuery; const Value: string; var KeyValue: Variant);
begin
  if not q.Active then exit;
  KeyValue := q.Lookup('name', Value, 'ID');
end;

 

 

 

Screenshot_12.jpg

Screenshot_13.jpg

Link to comment
Share on other sites

Честно говоря, я думал, что в событии

procedure comboOnGetKeyValue(q: TUniQuery; const Value: string; var KeyValue: Variant);
begin
  if not q.Active then exit;
  KeyValue := q.Lookup('name', Value, 'ID');
end;

 

KayValue запомниться и потом, позже можно будет прочитать это значение.

Получается, что я присвоил значение KayValue в событии OnGetKeyValue, но оно не присвоилось.

Link to comment
Share on other sites

Еще одна серьезная проблема.

Что произойдет, если в списке окажется две разных записи с одинаковыми названиями? Да, такое возможно.

Например, пользователь из двух одинаковых выберет вторую. А в событии OnGetKeyValue есть код Lookup(), где будет выбрана первая найденная запись, т.е. не та, которую выбрал пользователь.

Link to comment
Share on other sites

Нужно сэмулировать, что датасет на форме один для всех. Поэтому каждый раз при выборе значения я закрываю и открываю ClientDataSet1, потом очищаю его и наполняю новыми данными, как будто - это данные из разных таблиц базы.

Как воспроизвести ошибку?

1. Выбрать что-то из верхнего списка и нажать первую кнопку "Show KeyValue". Появится значение.

2. Выбрать что-то из нижнего списка и нажать вторую кнопку "Show KeyValue". Появится значение.

...пока ошибок нет...

3. Теперь снова что-то выберите в верхнем списке и снова нажмите первую кнопку "Show KeyValue" и вот тут уже Caption кнопки покажет проблему.

4. Теперь снова что-то выберите и снова в верхнем списке и снова нажмите первую кнопку "Show KeyValue" и вот тут уже Caption кнопки покажет KeyValue.

Можете попеременно выбирать что-то и нажимать соответствующую кнопку.

Надеюсь понятно описал проблему.

UniGUI_Touch_Scroll.zip

Screenshot_1.jpg

Link to comment
Share on other sites

On 7/27/2020 at 5:53 PM, x11 said:

Нужно сэмулировать, что датасет на форме один для всех. Поэтому каждый раз при выборе значения я закрываю и открываю ClientDataSet1, потом очищаю его и наполняю новыми данными, как будто - это данные из разных таблиц базы.

Вы можете проанализировать и использовать этот подход:

1. 

Uses ..., uniGUIJSUtils;

2. 

procedure TUnimLoginForm2.UnimLoginFormCreate(Sender: TObject);
begin
  with UnimDBLookupComboBox1, UnimDBLookupComboBox1.JSInterface do
  begin
    RemoteQuery := True;
    RemoteQueryCache := True;
    RemoteQueryDelay := 500;
    RemoteQueryRetainResult := True;
    Mode := umNameValue;

    JSConfigObject('store', 'proxy',
      [JSObject(
        ['type', 'ajax',
         'url', JSStatement(GetDataEventUrl(JSControl, 'items')),
         'reader', JSObject([
             'type', 'json',
             'responseType', ''
         ]),
        'timeout', 30000
      ])]
    );
  end;
end;

3. 

procedure TUnimLoginForm2.UnimDBLookupComboBox1AjaxEvent(Sender: TComponent;
  EventName: string; Params: TUniStrings);
begin
  if EventName = 'data' then
    if Params['root'].AsString = 'items' then
    begin
      //Здесь Вы можете использовать JSON модули
      UniSession.SendResponse('[{id: 5, val: "testVal"}, {id: 7, val: "testVal1"}, {id: 8, val: "testVal1"}]');
    end;
end;

 

Link to comment
Share on other sites

Проблема в том, что KeyValue не заполняется, если использовать режим "RemoteQuery". Вернее, оно заполняется, но при чтении значения, оно пустое.

1. Заполняю TUnimDBLookupComboBox. И видно, что свойству KeyValue значение присвоилось.

2. Видно в браузере, что и значение ListName тоже заполнено и выбрано.

3. Но при чтении уже unussigned.

Было бы здорово, если бы TUnimDBLookupComboBox не терял значение KeyValue.

Я так понимаю, что TUnimDBLookupComboBox теряет значение KeyValue из-за того, что нет подключенного датасета, свойство ListSource - пустое.

 

procedure comboSetValFromRef(combo: TUnimDBLookupComboBox; qRef: TUniQuery; idKey: integer; const ListField, sTable: string);
begin
// заполнить список одной строкой

  if not qRef.Active then
  begin
    qRef.SQL.Text := 'SELECT ID, NAME FROM ' + sTable + ' WHERE ID = ' + idKey.ToString;
    qRef.Open;
  end;

  if qRef.RecordCount > 0 then
  begin
    combo.JSInterface.JSCode(#1'.store.add({"id":' + idKey.ToString + ', "val":"'+ qRef.FieldByName(ListField).AsString + '"});');
    combo.JSInterface.JSCall('setValue', [idKey]);
    combo.KeyValue := idKey;
    qRef.close;
  end;

end;

 

Screenshot_6.jpg

Screenshot_7.jpg

Screenshot_8.jpg

Link to comment
Share on other sites

Ок, ладно... Если TUnimDBLookupComboBox в режиме "RemoteQuery" теряет keyValue, то как в таком режиме прочитать - какой индекс выбрал пользователь? Т.е. , например, в списке что-то выбрано (программно или пользователем), то нужно в любой момент времени прочитать ключевое значение - что выбрано. Как это сделать?

что-то вроде
 

Var
  idKey: string;
begin
...
...
...
  idKey := combo.JSInterface.JSCall('getKeyValue');

 

Link to comment
Share on other sites

16 minutes ago, x11 said:

Если TUnimDBLookupComboBox в режиме "RemoteQuery" теряет keyValue

Здравствуйте,

Не пробовали использовать это обходное решение?:

 

Link to comment
Share on other sites

Я пытался разобраться, но так и не понял до конца, что там происходит. Какие-то переменные, значения передаются в бразуер.

А как получить выбранное значение, я так и не понял.

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...