I now meet another problem using pgapp which is just epgsql+poolboy - textbox_autocomplete is throwing a bad_generator error from a proplist build from a DB query:
=INFO REPORT==== 9-Dec-2021::23:56:05.696236 ===
{error,postback_request,
{url,"nitrogen.defcon1.lan/offer/create"},
{error,
{bad_generator,ok},
[{offer_create,'-autocomplete_enter_event/2-lc$^1/1-1-',2,
[{file,
"/home/niff/ERLANG/SITES_NITROGEN/emploi/site/src/offer_create.erl"},
{line,806}]},
{offer_create,autocomplete_enter_event,2,
[{file,
"/home/niff/ERLANG/SITES_NITROGEN/emploi/site/src/offer_create.erl"},
{line,806}]},
{element_textbox_autocomplete,event,1,
[{file,"src/elements/forms/element_textbox_autocomplete.erl"},
{line,57}]},
{wf_core,run_websocket,1,[{file,"src/wf_core.erl"},{line,81}]},
{nitrogen,ws_message_catched,1,[{file,"src/nitrogen.erl"},{line,69}]},
{nitrogen,ws_message,3,[{file,"src/nitrogen.erl"},{line,59}]},
{cowboy_simple_bridge_anchor,websocket_handle,2,
[{file,
"src/cowboy_bridge_modules/cowboy_simple_bridge_anchor.erl"},
{line,70}]},
{cowboy_websocket,handler_call,6,
[{file,"src/cowboy_websocket.erl"},{line,482}]}]}}
this is the code involved:
autocomplete_enter_event(SearchTerm, _Tag) ->
%% If the session VAR is undefined, fill it, otherwise, return it
Proplist = case wf:state(towns_proplist) of
undefined ->
%% Retrieve all towns for autocompletion from DB (only the list of columns)
{ok, _, ListTownsIds} = e_db:get_all_towns()
, ?PRINT(ListTownsIds)
%% Convert it to a map, for we'll need to retrieve "id", which is the
%% town's name shorcut we'll need when saving this offer
%% (key=full name, value=shortcut=="id" col)
%% Retrieve Ex: maps:find(<<"Nantes">>, MapTowns.
%% {ok,<<"nan">>}
, wf:state(map_towns, maps:from_list(ListTownsIds))
, ?PRINT(wf:state(map_towns))
%% Build the proplist
%% FUCK ! ALL BINARIES w/ DIACRITICS HAVE WRONG (ISO-8859-1|15 ?) CHARS :(((
%% IT WAS BECAUSE THIS FILE HADN'T THE UTF8 HEADR (SEE LINE# 1) !
, wf:state(towns_proplist,
[[{id,string:lowercase(X)},{label,X},{value,X}] || {X, _} <- ListTownsIds]);
%, wf:state(towns_proplist,
% [[{id,string:lowercase(unicode:characters_to_binary(X,utf8))},{label,unicode:characters_to_binary(X,utf8)},{value,unicode:characters_to_binary(X,utf8)}] || {X, _} <- ListTownsIds]);
%wf:state(towns_proplist,
% [[{id,unicode:characters_to_binary(string:lowercase(X))},{label,unicode:characters_to_binary(X)},{value,unicode:characters_to_binary(X)}] || {X, _} <- ListTownsIds]);
_ ->
wf:state(towns_proplist)
end
, ?PRINT(wf:state(towns_proplist))
%% Let's filter the list based on the SearchTerm
, Data = [LangRec || LangRec <- Proplist, does_search_match(LangRec, SearchTerm)] <<< LINE# 806
, ?PRINT(Data)
%% Encode the Data into json for the autocomplete event. As you can see
%% from the base_data function below, it expects each record to have an
%% "id", a "label", and a "value". "id" is a short-hand identifier. "label"
%% is what will be displayed in the dropdown, and "value" will be passed
%% along with the "id", then decoded from json and sent to the
%% autocomplete_select_event function as a proplist.
, wf:json_encode(Data).
does_search_match(LangRec, SearchTerm0) ->
% OK, LA Fn CI-DESSUS ENVOIE UN PAR UN LES ÉLÉMENTS (LISTE DE TUPLES) ICI
%?PRINT(LangRec),
%% We extract the label from the passed Lang "Rec" (which is just a proplist)
Label0 = proplists:get_value(label, LangRec)
%% And convert it ot lower case
, Label = string:to_lower(wf:to_unicode_list(Label0))
%% and also convert the SearchTerm to lowercase
, SearchTerm = string:to_lower(SearchTerm0)
%% Then see if SearchTerm is contained anywhere in the Label
, string:str(Label, SearchTerm) > 0.
autocomplete_select_event(SelectedElement, _Tag) ->
%% SelectedElement is a proplist
%% Let's tell the user what we selected!
wf:flash(proplists:get_value(<<"value">>, SelectedElement))
, ok.
The problem seems to be tied to a character problem (oh nooo! I thought there wasn't any anymore:( as ?PRINT(ListTownsIds) displays a bad list with odd characters:
=INFO REPORT==== 9-Dec-2021::23:56:05.695021 ===
DEBUG: <0.24257.4>
offer_create:784
"ListTownsIds"
[{<<"Basse-Goulaine">>,<<"basgou">>},
{<<"Bouaye">>,<<"bouaye">>},
…
{<<"St-Léger les Vignes">>,<<"stlegv">>},
{<<"St-Sébastien sur Loire">>,<<"stseb">>},
{<<"Thouaré sur Loire">>,<<"thoua">>},
…
Note that the same thing done from the Nitrogen console returns a ferpect ouput.
The query is pretty simple:
get_all_towns() ->
pgapp:squery("SELECT town,id FROM tab.town ORDER BY town").
which normally returns (done manually from the nitrogen console):
(emp...@127.0.0.1)95> e_db:get_all_towns().
{ok,[{column,<<"town">>,varchar,1043,-1,52,0,39351,2},
{column,<<"id">>,varchar,1043,-1,10,0,39351,1}],
[{<<"Basse-Goulaine">>,<<"basgou">>},
{<<"Bouaye">>,<<"bouaye">>},
…
{<<"St-Léger les Vignes"/utf8>>,<<"stlegv">>},
{<<"St-Sébastien sur"/utf8...>>,<<"stseb">>},
{<<"Thouaré sur "/utf8...>>,<<"thoua">>},
…
So, once again I'm stuck - where am I wrong?
Jean-Yves