electron 电子打开文件夹对话框关闭后,输入值未更新

qnzebej0  于 2022-12-16  发布在  Electron
关注(0)|答案(1)|浏览(228)

我有一个组件,我将它附加到一个input上,以按照我想要的方式对其进行样式化。

@Component({
  selector: 'input[ui-input]',
  template: '',
  styleUrls: ['./input.component.scss'],
})
export class InputComponent {}

然后我在html中使用它,就像下面一样。我还有一个按钮,我点击它可以打开一个文件夹选择,也可以在下面看到。

<ui-form-field *ngIf="home$ | async">
  <label ui-label>Default Project Location</label>
  <input ui-input [(ngModel)]="home" />
  <div ui-form-field-actions>
    <button ui-button-fab (click)="selectFolder()">
      <fa-icon [icon]="browseFolderIcon"></fa-icon>
    </button>
  </div>
</ui-form-field>

我附加到它的组件如下所示:

@Component({
  selector: 'app-settings',
  templateUrl: './settings.component.html',
  styleUrls: ['./settings.component.scss'],
})
export class SettingsComponent {
  home = '';
  home$ = of(this.settings.get<string>('default-save-location')).pipe(
    tap(i => (this.home = i))
  )

  selectFolder() {
    this.electron
      .openFolder()
      .pipe(
        tap(i => console.log(i)),
        tap(i => (this.home = i))
      )
      .subscribe();
  }
}

当组件加载时,home会被设置并将值呈现到输入中,然而,当selectFolder()运行时,新值会被记录到控制台,但模板不会更新,除非我在input内部单击,然后在input外部单击。
我也没有在任何组件上设置changeDetection,所以它们都使用默认的更改检测策略。
不确定是否相关,但我在电子服务中有这个:

@Injectable({ providedIn: 'root' })
export class ElectronService {
  private home = new BehaviorSubject('/');
  home$ = this.home.pipe(switchMap(() => this.#getItem<string>('path', 'home')));

  openFolder() {
    return this.#getItem<{ filePaths: string[] }>('open-folder').pipe(
      map(i => i.filePaths?.[0] ?? ''),
      take(1)
    );
  }

  #getItem<T, U = unknown>(key: string, ...args: U[]) {
    return new Observable<T>(sub => {
      window.ipcRenderer.once(key, (e, v) => {
        sub.next(v);
        sub.complete();
      });
      window.ipcRenderer.send(key, ...args);
    });
  }
}
unftdfkk

unftdfkk1#

我可以通过在electronic main服务中使用contextIsolation创建一个preloader来解决这个问题。我还添加了一个对话框处理程序来处理对话框的打开:

let win: BrowserWindow;

app.on('ready', () => {
  win = new BrowserWindow({
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js'),
    },
  });

  ipcMain.handle('dialog', (evt, method: any, ...params: any[]) => dialog[method](...params));
});

接下来,在预加载器中,我添加了一个上下文桥来向渲染器公开一些函数:

contextBridge.exposeInMainWorld('electron', {
  dialogOpen: (method: string, options: any) => ipcRenderer.invoke('dialog', method, options),
});

接下来,在渲染器进程中,我只需要调用dialogOpen函数:

openFolder() {
    return from(
      window.electron.dialogOpen('showOpenDialog', { properties: ['openDirectory'] })
    ).pipe(
      map(i => i.filePaths?.[0] ?? ''),
      take(1)
    );
  }

这不仅解决了这个问题,而且我不再需要调用window.ipcRenderer.send(),然后创建一个侦听器来侦听响应,该函数只返回一个带有结果的promise!

相关问题