最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Externally pass values to an Angular application - Stack Overflow

programmeradmin5浏览0评论

I'm thinking of separating our MVC-based website's front-end into few ponents and I was thinking about using Angular for that purpose (e.g. creating cart application that I can include to my view afterwards).

Problem is that I need to pass few variables into that application and I'm wondering how to do that safely and professionally. I was thinking about something like:

  1. I'm going to ng build --prod --aot
  2. I inject all my scripts to my view
  3. I inject variables passed to view to my app

... and "code" representation for my thoughts:

Controller:

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
}

View:

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

So my question is... would it be possible (and would it be a good solution) to get the CartApp as an object and then make some function (like use in above example) that would set/pass the data? (let's say to some globally provided service/ponent or anything else). Or is there any other way to do this? Like taking the variables from inside the application from the window object? (as they're going to be bound to the window anyways). Thank you.

I'm thinking of separating our MVC-based website's front-end into few ponents and I was thinking about using Angular for that purpose (e.g. creating cart application that I can include to my view afterwards).

Problem is that I need to pass few variables into that application and I'm wondering how to do that safely and professionally. I was thinking about something like:

  1. I'm going to ng build --prod --aot
  2. I inject all my scripts to my view
  3. I inject variables passed to view to my app

... and "code" representation for my thoughts:

Controller:

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
}

View:

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

So my question is... would it be possible (and would it be a good solution) to get the CartApp as an object and then make some function (like use in above example) that would set/pass the data? (let's say to some globally provided service/ponent or anything else). Or is there any other way to do this? Like taking the variables from inside the application from the window object? (as they're going to be bound to the window anyways). Thank you.

Share Improve this question edited Aug 17, 2017 at 18:56 Dawid Zbiński asked Aug 17, 2017 at 10:13 Dawid ZbińskiDawid Zbiński 5,8268 gold badges50 silver badges76 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 16 +50

So I was going to suggest using input bindings... I've done that before in AngularJS but was surprised to find that using input bindings on the root ponent isn't supported yet. You can have fun reading this giant issue: https://github./angular/angular/issues/1858

The best post I saw there was Rob Wormald's which had a couple of suggestions:

  • to the initial question, if you really want to grab data from the root, that's possible via https://plnkr.co/edit/nOQuXE8hMkhakDNCNR9u?p=preview - note that it's not an input (because there's no angular context outside of it to do the input...) - its a simple string attribute which you'd need to parse yourself.
  • ideally though, you'd do as @robtown suggested and actually pass the data in javascript, rather than passing it as a DOM string and retrieving / parsing it yourself (which has never really been a supported case in angular, despite the explicit-warned-against usage of ng-init in angular1 to acplish this) - see https://plnkr.co/edit/PoSd07IBvYm1EzeA2yJR?p=preview for a simple, testable example of how to do this.

So the 2 good options I saw were:

  1. Add normal HTML attributes to the root ponent:

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

    and use ElementRef to fetch them:

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

    Would probably work best if you are just dealing with strings or config flags. If you are passing JSON, you will need to manually parse it.

  2. Have the server render the data as JavaScript and import it in your app:

    Have the server render something like this to a script tag or JS file that is loaded before Angular is bootstrapped:

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

    Tell your NgModule about it using a provider:

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

    And then use it as a normal Angular service:

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

评论列表(0)

  1. 暂无评论