Modification sous formulaire

J’ai un sous formulaire dans un hôte.
La variable liée est de type objet.
Dans l’hôte, la méthode du sous formulaire fait ça :

Case of 
: (Form event=On Data Change)
//do some stuff
End case

Dans le code interne au sous formulaire, je fais ça :

Form.donnees:= maMethodeObjet
CALL SUBFORM CONTAINER(On Data Change)

ou plutôt « je suis obligé de faire » sans piger pourquoi… Puisque la première ligne modifie la variable liée, elle devrait déclencher “on data change” au niveau de l’hôte, il me semble. Or rien ne se passe, je dois “forcer” avec le CALL SUBFORM CONTAINER en seconde ligne.

Tu veux faire quoi ?

C’est parce que un objet est une référence …

Et du coup le conteneur est “insensible” au variations du contenu, si je te suis… Y’a moyen de le sensibiliser autrement ?

C’est un widget de recherche. Une fois qu’il a fait des trucs avec la saisie utilisateur, l’hôte est prié de s’en apercevoir.

selon je ne sais plus quelle loi, l’hôte doit ignorer ce que fait le sous formulaire. Tu valorises ton objet quand c’est finit et tu fais CALL SUBFORM CONTAINER (-1), si c’est -1 l’hôte sait ce qu’il lui reste à faire.

Oui, mais ils ont quand même une “zone d’échange”, la variable liée. Si elle était de type date, par exemple, au lieu d’être un objet, le changement de sa valeur par le sous formulaire déclencherait le “on data change” dans l’hôte.

femt

Arnaud,
Could you include a reference to the search destination in the subform? The widget populates this object or collection, which is already on the parent form.

But if you also need to initiate an action on the parent form I think CALL SUBFORM CONTAINER is the best option.

It took me a little while to figure out the On bound variable change event doesn’t help much when the container variable is an object.

worse with me, I’m afraid it’s not the 1st time I fall in this trap :frowning:

I’m not sure to understand your question, maybe if I describe what I (try to) do it will be more clear. The goal of that widget is to “pre process” user input on the basis of patterns, not to query, that will be the host job.

Let’s say (input -> preprocessed):

  • “hello” -> string, 1 value
  • “123” -> real, 1 value
  • “123…456” -> real, 2 values
  • “1-1-20” -> date, 1 value
  • “1-1-20…12-120” -> date, 2 values

Then the host reads the preprocessed object and sends query according to its context:
case of
:(string)
query on customer name
:(date with 2 values)
query on invoice date between these 2 days
:(real with 2 values)
query on invoice amount between these 2 numbers
end case

PS j’espère être compréhensible en français :wink:

Arnaud,
So the purpose of the subform is to act like a function?
I was thinking it was more the case where the subform receive the user input and do some sort of query. To illustrate the idea

 	$subform_form:=New object
	$subform_form.input:=""
	$subform_form.preprocessed:=""
	Form.subform_form:=$subform_form
	
	OBJECT Get pointer(Object named;"subform")->:=$subform_form
	
	  // --------------------------------------------------------
	  //  to use it
	Form.subform_form.input:="input string"
	EXECUTE METHOD IN SUBFORM("subform";"methodName")
	
	  //  Form.subform_form.preprocessed = result

But in your case what is the benefit of using a subform vs. just using a method?

Forget OBJECT Get pointer(Object named;“subform”), I put “Form.subform” in the expression property :wink:

It’s a kind of “generic UI function”, a bit similar to 4D’s search picker. I want the same look anywhere it’s used, the same way to analyse the user input, the same trigger (return key), and some other goodies. But I want the host to do the query, the widget is and must be blind to its host.

The returned objet is something like:
{type : is real
input : “123…456”
values [123,456]
}

The generic part is the parsing of the input. Above the widget says “I’ve interpreted input as 2 numbers”, but I’m free in host to use or not this information. The user knows it’s useless to enter a number if there is no number to query in a given context. But, at the same time, if there is a number or date column, I can guess from the input where to query in.

Fouille la doc ?

Au niveau du sub-form, il y a “on boud variable change” event. Tu changes depuis le host, et cela trigger le event dans le sub-form à la fin de ta méthode qui modifie.

Dans l’autre sens ? Ca doit le faire, MAIS : j’ai eu des soucis. L’objet associé au sous-formulaire existe toujours, mais…

L’objet peut être créé automatiquement ou être la variable du conteneur parent, si elle a été explicitement nommée et typée Objet (voir ci-dessus)

Ca c’est pénible, car cela veut dire que tu dois utiliser une variable process bêtement. Je ne sais pas pourquoi 4D a fait ainsi. Et j’ai tout essayé pour définir l’objet depuis le host, sans utiliser de variable process dans le host sans succès. Je souhaitais que toutes les options de mes widgets de ogTools soient directement dispo avec self-> dans l’instance, mais je n’y ai pas réussi.

Donc dans ton cas, je suppute que tu n’as pas d’objet déclaré dans ton instance host. Et que tu utilises le OBJECT Get pointer (Object named;“my_object”) pour y accéder ?

Bonjour Olivier,
non, coté hôte, comme je mets l’expression “Form.monSousFormulaire” en propriété, ce n’est pas “pointable”. Pas de variable process, pas bien :joy:

Ça fait un bout de temps que j’utilise des sous formulaires et que régulièrement je loupe une étape qui mets tout par terre. Puis je passe un temps fou à retrouver. Existe-t-il un “how do I” qui s’appellerai “créer un sous formulaire avec variable liée de type objet pour les nuls” ?

Arno,

Dans ce cas, avant tout dans ton formulaire Hôte tu dois déclarer un truc du type

OBJECT Get pointer(Object named;“monSousFormuliare”)->:=Form.subForm

Form doit être valorisé et ici Form.subForm est l’objet du container sans nom de variable objet.
et tu aurais par exemple ta capsule de recherche “search” avec Form.subForm.search:=""

Une fois cette variable valorisée, tu récupères ton contenu Form.subForm.search dans le container

C_OBJECT($o)
$o:=OBJECT Get pointer(Object named;"monSousFormuliare")->
$search:=$o.search

Première contribution sur gitHub:

2 Likes

The how about adding a property named callback? When you initialize the subform add the method the host will execute. The input areas in the subform check for the presence of the callback On data change or On loosing focus, whatever is appropriate, and you use Execute method to run the callback.

Bear in mind the callback method runs in the context of the subform, however.

Hi Kirk,
I think I was unclear about my goal…
To make it clearer with another example, suppose a date calendar widget: I just want it to return host the chosen date, optionally a starting day for the first display from host. The host knows what to do with this date after. There is no need for host to send subform “execute a method”, the other way around not too. Here it’s the same : from the user input, the widget returns an interpretation of the input, whatever the host, nothing more.