x11 Posted July 27, 2020 Posted July 27, 2020 На форме есть много списков типа 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). Quote
Sherzod Posted July 27, 2020 Posted July 27, 2020 Попробуйте этот код: 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; 1 Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 3 minutes ago, Sherzod said: "id":0, так и должно быть или вместо 0 нужно подставить StrIntPair.key? Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 Ок, а как потом при чтении значения узнать KeyValue? Ведь в таблицу не записывается UnimDBLookupComboBox1.Text, а записывется UnimDBLookupComboBox1.KeyValue. Quote
Sherzod Posted July 27, 2020 Posted July 27, 2020 1 minute ago, x11 said: Ведь в таблицу не записывается UnimDBLookupComboBox1.Text, а записывется UnimDBLookupComboBox1.KeyValue. UnimDBLookupComboBox1GetKeyValue Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 Извините, всё равно не понял. Согласно вашему коду, при старте формы я заполняю ТОЛЬКО свойство TEXT. Потом, при закрытии формы, при сохранении данных в базу нужно откуда-то взять KeyValue. Как в данном случае использовать событии GetKeyValue? На момент закрытия формы KeyValue НИГДЕ нет. Никаких датасетов к UnimDBLookupComboBox1 не привязано. Quote
Sherzod Posted July 27, 2020 Posted July 27, 2020 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; Quote
Sherzod Posted July 27, 2020 Posted July 27, 2020 Если вы считаете, что этот подход не является оптимальным, то будем анализировать дальше... Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 В том-то и дело, что нет никаких ClientDataSet`ов. Я же показал код в первом сообщении. Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 Вот код при сохранении данных в базу: qSave.FieldByName('ID_SERVICE').AsInteger := comboServices.KeyValue; qSave.FieldByName('ID_STATE').AsInteger := comboState.KeyValue; qSave.FieldByName('ID_CURRENCY').AsInteger := comboCurr.KeyValue; тут использовать событие UniDBLookupComboBox1GetKeyValue никак не получится Quote
Sherzod Posted July 27, 2020 Posted July 27, 2020 28 minutes ago, x11 said: В том-то и дело, что нет никаких ClientDataSet`ов. А как Вы выбираете другие значения? Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 В общем, как оказалось, даже у тех 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; Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 Честно говоря, я думал, что в событии 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, но оно не присвоилось. Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 Получается, нужно где-то самому запоминать KeyValue? Например, в свойстве TAG. Quote
Sherzod Posted July 27, 2020 Posted July 27, 2020 Если у Вас есть возможность, сделайте простой тестовый случай с одним комбобоксом. Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 Кстати, очень неудобно, что в событиях TUnimDBLookupComboBox отсутствует параметр Sender: TObject Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 Еще одна серьезная проблема. Что произойдет, если в списке окажется две разных записи с одинаковыми названиями? Да, такое возможно. Например, пользователь из двух одинаковых выберет вторую. А в событии OnGetKeyValue есть код Lookup(), где будет выбрана первая найденная запись, т.е. не та, которую выбрал пользователь. Quote
x11 Posted July 27, 2020 Author Posted July 27, 2020 Нужно сэмулировать, что датасет на форме один для всех. Поэтому каждый раз при выборе значения я закрываю и открываю ClientDataSet1, потом очищаю его и наполняю новыми данными, как будто - это данные из разных таблиц базы. Как воспроизвести ошибку? 1. Выбрать что-то из верхнего списка и нажать первую кнопку "Show KeyValue". Появится значение. 2. Выбрать что-то из нижнего списка и нажать вторую кнопку "Show KeyValue". Появится значение. ...пока ошибок нет... 3. Теперь снова что-то выберите в верхнем списке и снова нажмите первую кнопку "Show KeyValue" и вот тут уже Caption кнопки покажет проблему. 4. Теперь снова что-то выберите и снова в верхнем списке и снова нажмите первую кнопку "Show KeyValue" и вот тут уже Caption кнопки покажет KeyValue. Можете попеременно выбирать что-то и нажимать соответствующую кнопку. Надеюсь понятно описал проблему. UniGUI_Touch_Scroll.zip Quote
Sherzod Posted July 27, 2020 Posted July 27, 2020 2 hours ago, x11 said: UniGUI_Touch_Scroll.zip Я постараюсь проанализировать. 1 Quote
Sherzod Posted August 4, 2020 Posted August 4, 2020 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; Quote
x11 Posted August 10, 2020 Author Posted August 10, 2020 Проблема в том, что 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; Quote
x11 Posted August 10, 2020 Author Posted August 10, 2020 Ок, ладно... Если TUnimDBLookupComboBox в режиме "RemoteQuery" теряет keyValue, то как в таком режиме прочитать - какой индекс выбрал пользователь? Т.е. , например, в списке что-то выбрано (программно или пользователем), то нужно в любой момент времени прочитать ключевое значение - что выбрано. Как это сделать? что-то вроде Var idKey: string; begin ... ... ... idKey := combo.JSInterface.JSCall('getKeyValue'); Quote
Sherzod Posted August 10, 2020 Posted August 10, 2020 16 minutes ago, x11 said: Если TUnimDBLookupComboBox в режиме "RemoteQuery" теряет keyValue Здравствуйте, Не пробовали использовать это обходное решение?: Quote
x11 Posted August 10, 2020 Author Posted August 10, 2020 Я пытался разобраться, но так и не понял до конца, что там происходит. Какие-то переменные, значения передаются в бразуер. А как получить выбранное значение, я так и не понял. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.