【问题标题】:Externally pass values to an Angular application从外部将值传递给 Angular 应用程序
【发布时间】:2018-01-25 16:56:12
【问题描述】:

我正在考虑将我们基于 MVC 的网站的前端分成几个组件,并且我正在考虑使用 Angular 来实现这个目的(例如,创建我可以在之后包含到我的视图中的购物车应用程序)。

问题是我需要将几个变量传递到该应用程序中,我想知道如何安全而专业地做到这一点。我正在考虑类似的事情:

  1. 我要去ng build --prod --aot
  2. 我将所有脚本都注入到我的视图中
  3. 我将传递给视图的变量注入到我的应用中

...和我的想法的“代码”表示:

控制器:

public function viewAction()
{
    $this->view->addCss('angular/app/styles.css'); // adds styles for cart app 
    $this->view->addJS('angular/app/scripts.js');  // adds scripts for cart app
    $this->view->setJSVariable('idCustomer', 555); // sets global var idCustomer
}

查看:

<!-- bunch of HTML for view ... -->
<script>
    // CartApp would be an angular app.
    CartApp.use([
        idCustomer
    ]);
</script>

所以我的问题是......是否有可能(并且这是一个很好的解决方案)将CartApp 作为一个对象,然后创建一些函数(如上面示例中的use)来设置/传递数据? (比方说一些全球提供的服务/组件或其他任何东西)。或者有没有其他方法可以做到这一点?就像从窗口对象中获取应用程序内部的变量一样? (因为无论如何它们都会被绑定到窗口)。谢谢。

【问题讨论】:

    标签: javascript angular typescript model-view-controller javascript-objects


    【解决方案1】:

    所以我打算建议使用输入绑定...我之前在 AngularJS 中做过,但惊讶地发现还不支持在根组件上使用输入绑定。您可以尽情阅读这个巨大的问题:https://github.com/angular/angular/issues/1858

    我在那里看到的最好的帖子是Rob Wormald's,其中有几个建议:

    • 对于最初的问题,如果您真的想从 根,这可以通过 https://plnkr.co/edit/nOQuXE8hMkhakDNCNR9u?p=preview - 请注意,它不是输入(因为在它之外没有角度上下文来进行输入......) - 它是一个简单的字符串属性 您需要自己解析。
    • 理想情况下,您应该这样做 @robtown 建议并实际在 javascript 中传递数据,而不是 而不是将它作为 DOM 字符串传递并自己检索/解析它 (尽管 明确警告反对在 angular1 中使用 ng-init 来完成 这个) - 见https://plnkr.co/edit/PoSd07IBvYm1EzeA2yJR?p=preview 如何做到这一点的简单、可测试的示例。

    所以我看到的两个不错的选择是:

    1. 为根组件添加普通的 HTML 属性:

      <app-root appData='important stuff'></app-root>
      

      并使用ElementRef 获取它们:

      @Component({
        selector: 'app-root'
      })
      export class AppComponent {
        constructor(el: ElementRef) {
          console.log(el.nativeElement.getAttribute('appData'));
        }
      }
      

      如果您只是处理字符串或配置标志,可能效果最好。如果传递 JSON,则需要手动解析。

    2. 让服务器将数据呈现为 JavaScript 并将其导入您的应用:

      让服务器在启动 Angular 之前将这样的内容渲染到脚本标签或加载的 JS 文件:

      window.APP_DATA = { ids: [1, 2, 3] }
      

      使用提供者告诉你的 NgModule:

      import { BrowserModule } from '@angular/platform-browser';
      import { NgModule } from '@angular/core';
      
      import { AppComponent } from './app.component';
      
      @NgModule({
        providers: [{ provide: 'AppData', useValue: (<any> window).APP_DATA }],
        bootstrap: [AppComponent]
      })
      export class AppModule { }
      

      然后将其用作普通的 Angular 服务:

      import {Component, Inject} from '@angular/core';
      
      @Component({
        selector: 'app-root'
      })
      export class AppComponent {
        constructor(@Inject('AppData') appData) {
          console.log(appData.ids);
        }
      }
      

    【讨论】:

    • 这正是我想要的。尤其是第二种方式看起来很不错。非常感谢@Scotty。
    • 我实际上有一些时间来查看它,但我无法像您在第二个示例中那样提供AppData。我遇到的错误是... AppData (未指定 provide 的值(可能应该首先提供),第二个是窗口没有 APP_DATA 属性(因为它不是已知的Window inerface 的属性)。您能否为您的答案的第二个示例添加更多代码示例?不仅适用于我,也可能适用于其他有相同问题的用户。谢谢。
    • 我更新了代码。我没有实际测试过它,而是从示例中编译了它。对于那个很抱歉。我没有试图让打字正确。为您的 APP_DATA 创建一个接口,将其导入组件中,并在将其注入构造函数时使用它可能会很好:constructor(@Inject('AppData') appData: MyAppDataInterface)。让我知道我更新的代码是否适合您。主要更改是在provide: 字段中使用字符串、使用(&lt;any&gt; window) 和使用@Inject。可能有更清洁的方法,所以如果你发现任何改进,请告诉我:)
    • @ScottyWaggoner 公平的答案,但如果在控制器 ViewData['somvalue'] 中存储了某个值,那么我怎么能将该值发送到 index.html,它位于 ClientApp 目录中。
    • 非常感谢您的回答!在 2021 年,任何想法如何将参数从原生 JS 传递到组件中?例如,我有 Angular 应用程序作为地图。如何在其他应用中使用用户配置?
    猜你喜欢
    • 2020-11-14
    • 2017-01-19
    • 2019-02-16
    • 2019-05-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多