How to use WebOpenDialog

Hi.

Do you have an example with WebOpenDialog? The workflow is not similar to the traditional OpenDialog.
1- The "Execute" does not return a bool value. How do we know if a file is selected or the users selected "Cancel?
2- The "Filename" attribute shows only file name and not the path to the file. I cannot find the path in any other attribute.
3- The selected filename is not available until the next execute call. After the first exec the filename is empty. Next time it has the previous file name.

Can you provide a working example?

BR
Amin

Please have a look at the upload example. It is available in Basics/Upload. Remember that there is no traditionalopen file dialog in web application. Web applications cannot access local resources. Only the web browser can upload local resources and that whole functionality depends on your browser and not the web application.

There is a separate component for use in Electron applications which allow access to local resources.

Hi
I am confused. The following is from the Web Core documentation:

The TWebOpenDialog non-visual component allows to start a dialog to pick files from the local file system.

I want to do exactly that. Do you mean that I cannot do that? I cannot even get the file name. Is there any example with WebOpenDialog?

The "Upload" example is using a WebFilepicker. Not exactly the workflow I am looking for.

Can I put an ElectronOpenDialog and use it on Web application project? I get the following error If I do run the application:

ERROR
Uncaught TypeError: Cannot read property 'ipcRenderer' of null | TypeError: Cannot read property 'ipcRenderer' of null at Object.InitPaths (http://localhost:8000/Tina_FNC/Tina_FNC.js:142121:35) at Object.ElectronPath (http://localhost:8000/Tina_FNC/Tina_FNC.js:142626:19) at Object.$mod.$init (http://localhost:8000/Tina_FNC/Tina_FNC.js:142689:10) at loadimpl (http://localhost:8000/Tina_FNC/Tina_FNC.js:213:46) at Object.loaduseslist (http://localhost:8000/Tina_FNC/Tina_FNC.js:189:7) at loadimpl (http://localhost:8000/Tina_FNC/Tina_FNC.js:201:9) at Object.loaduseslist (http://localhost:8000/Tina_FNC/Tina_FNC.js:189:7) at loadimpl (http://localhost:8000/Tina_FNC/Tina_FNC.js:201:9) at Object.loaduseslist (http://localhost:8000/Tina_FNC/Tina_FNC.js:189:7) at Object.loadimpl (http://localhost:8000/Tina_FNC/Tina_FNC.js:201:9)
at http://localhost:8000/Tina_FNC/Tina_FNC.js [142121:35]

BR
Amin

Sorry for causing confusion. That was not my intent.

First, no, you cannot use Electron components in a ‘normal’ web application. Electron applications are special.

The file picker also allows you to select files and get the list of files the user selected. There is no need for an upload.

However, I will look at TWebOpenDialog asap and will give you an answer asap. I apologize, but TMS WEB Core is offering so much that I mixed things up. My mistake, I will look into it.

Place a TWebButton and TWebOpenDialog on the form. Also, drop a TWebMemo.

image

The call to Execute is non-blocking. That means, the event OnChange has to be used to determine when the dialog has been closed and files have been selected. If the user clicks cancel, no files are added to the Files property of the dialog and the event is not triggered.

Here's a possible implementation to list all selected files in the memo control.

procedure TForm1.DialogChange(Sender: TObject);
var
 i : Integer;

begin
  for i := 0 to  Dialog.Files.Count - 1 do
  begin
    WebMemo1.Lines.Add( Dialog.Files[i].Name) ;
  end;
end;

procedure TForm1.WebButton1Click(Sender: TObject);
begin
  Dialog.Execute;
end;

Hello Holger,

I have the same question about this component. I don't understand what exactly is its purpose.

Yes, I realize that you can use it to select a file and then you can display the file name that you selected.

Okay, fine. And then what happens after that?

How can I do something useful after I've selected a file with TWebOpenDialog?

In TMS WEB Core Demos\Fnc\Blox\ it is used twice, as for opening a Blox file, and for opening a picture into an image object.

procedure TForm5.DoOpenFile(Sender: TObject);
var
  w: TWebOpenDialog;
begin
  w := TWebOpenDialog.Create(Self);
  w.Accept := '.blx';
  w.OnChange := DoOpenFileChanged;
  w.Execute;
end;

procedure TForm5.DoOpenFileChanged(Sender: TObject);
begin
  TMSFNCBloxControl1.LoadFromFile((Sender as TWebOpenDialog).Files[0].FileObject);
end;

procedure TForm5.DoOpenPicture(Sender: TObject; AElement: TTMSFNCBloxElement);
var
  w: TWebOpenDialog;
begin
  w := TWebOpenDialog.Create(Self);
  w.Accept := '.svg,image/*';
  w.OnChange := DoOpenPictureChanged;
  w.Execute;
end;

procedure TForm5.DoOpenPictureChanged(Sender: TObject);
begin
  TTMSFNCUtils.LoadFile((Sender as TWebOpenDialog).Files[0].FileObject, @DoFileLoaded);
end;

procedure TForm5.DoFileLoaded(const AFile: TTMSFNCUtilsFile);
var
  b: TTMSFNCBloxElement;
  base64: string;
begin
  base64 := TTMSFNCUtils.FileToBase64(AFile);

  if TMSFNCBloxControl1.Presenter.SelectedCount > 0 then
  begin
    b := TMSFNCBloxControl1.Presenter.Selecteds[0];
    if b.isBlock then
    begin
      (b as TTMSFNCBloxBlock).Picture.Stream.OnChange := DoPictureChanged;
      (b as TTMSFNCBloxBlock).Picture.LoadFromFile('data:image/svg+xml;base64,' + base64);

    end;
  end;
end;

Thanks for pointing to the Blox demo.

Unfortunately, that particular example doesn't work for my situation. In the Blox demo, they're calling:

TMSFNCBloxControl1.LoadFromFile((Sender as TWebOpenDialog).Files[0].FileObject);

And in that particular case, the LoadFromFile procedure is expecting a TJSHTMLFile parameter.

When I try to adapt that code to my own program using:

WebMemo1.Lines.LoadFromFile((Sender as TWebOpenDialog).Files[0].FileObject);

I get a compiler error:

[Error] WebOpenDialogTestUnit.pas(131): Incompatible type arg no. 1: Got "TJSHTMLFile", expected "String"

This whole thing is incredibly frustrating. I'm trying to do something which (I believe) should be very simple, and yet it's proving to be impossible.

I simply want to use a WebOpenDialog to select a text file and then display the contents of the text file in a memo.

If this is not possible, I wish somebody from TMS would just reply and say "Sorry, that's not possible."

But so far my calls for help are being ignored. I originally tried posting this question in a different thread ten days ago, and received no responses. Now I tried this thread, and still getting no responses.

Instead of LoadFromFile, use:

TWebOpenDialog(Sender).Files[0]
  .GetFileAsText(
    procedure (txt : string)
      begin 
        webmemo1.Lines.Text := txt; 
      end
  );
1 Like

Thank you, Julio.

It works perfectly.

I wish TMS would create some more events in TWebOpenDialog to handle things like GetFileAsText, GetFileAsBase64, etc., so that we wouldn't have to use ugly anonymous methods.

The events at TWebOpenDialog level will be available in the next update.

Thank you - that would be an excellent update.

I'm stuck at the example in the manual (V1.9.7.0 Sentina) for TWebOpenDialog that won't compile.

All I'm trying to do is display a File Open dialog when the user clicks a button. I cannot find anything that compiles. The selected filenames need to be put into a TWebListBox. I'm guessing that I need to use GetFileAsURL event to get the filenames? But it's not clear how.

When the user clicks on one of the files in the listbox, I want that file (an .mp4 file) to be loaded into a TTMSFNCWXVideoPlayer that's on the form.

I have a TWebButton and I pasted the sample code into the OnClick handler, and I get an error on the line fn := await(string, WebOpenDialog1.Perform); saying:

[Error] frmMain.pas(42): await only available in async procedure

I'm not sure where this sample code belongs.

I've tried other approaches, but nothing compiles.

The Methods chart shows an option for Execute as:

Execute(AProc: TOpenDialogProc);

but Delphi won't recognize it.

The example is inadequate. It needs more context and how different properties and methods work together, because it seems that some are for sync uses while others are for asynch uses.

Also, the Events other than OnChange are not documented in the manual.

I'm working with D10.4.2 and I have WebCore V1.9.7.0 installed.

Ignore my post above. I can no longer edit it.

It appears that Holger made a video on this topic here:

However, it's from before the new events were added.

It would be nice if the manual showed a more complete example, including at least one of the new events.

As an aside, if I want to load one or more *.mp4 files into a list, do I want to save the names as a URL if they're going to be loaded into the FNC media player component?

Also, the manual shows a version of Execute that takes a Proc parameter, but the compiler does not recognize it as far as I could tell.

Basically it is a 2 step process:

  1. You get the OnChange event triggered when one or more files were selected
  2. To get the file, call WebOpenDialog.Files[x].GetFileAs* and the equivalent event OnGetFileAs* will be triggered.

If you want to load a local file in an FNC media player, do a load as base64 and assign the media player URL to this base64 data URL.

WebOpenDialog.Execute has no proc param.

How would one go about selecting a relatively large local (MP3) file on a desktop / laptop via TWebOpenDialog, then upload it to a server via a php script using TWebHttpRequest? Is this even possible in WEB Core?

TWebOpenDialog apparently won't return a full pathname. Instead, it uses a pass-by-value model, so it must inhale the entire file into memory, then pass it along to the next thing, which in this case would be a TWebHttpRequest object. I'm not sure what it wants if not a filename; but if you can give it the entire file (in memory) then how do you ensure it's in the expected format? And how do you pass it in?

It's OK to restrict this to running on a desktop or laptop where the user has access to the entire file system.

BTW, why does this dialog have three different properties to get returned: Name, DisplayName, and GetNamePath, which all return the same thing? (Actually, iterating through the TFiles collection, DisplayName and GetNamePath both return "TFile".)

Get the file as ArrayBuffer with TWebOpenDialog.
Then you have in the event OnGetFileAsArrayBuffer the entire file in memory accessible per byte.
If you want to check the format, you'd need to check the file header here.
Then you can use a TWebHttpRequst to post this data (in the format the server expects) to the server to upload.

Thanks. Again, a code example would be greatly appreciated because the TWebHTTPRequest component is very different from most others I've seen, and I haven't seen a single example of a POST request that uploads data. It does not need to be a fully-working project, just something that shows all of the pieces you need to plug-in to make it work.

As I explained in another thread, it depends on the backend and how you handle POST at the backend and expect data there. What do you have at the backend? How does your backend expect the POST data?

Hi David..

If you still need an example for POST, let me know.

I have several projects where the back end is an Indy web server. In some cases, the client side is POSTing a file, and other cases it's POSTing the values of a TStringList.