Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Externally pass values to an Angular application

I'm thinking of separating our MVC-based website's front-end into few components 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/component 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.

like image 725
Dawid Zbiński Avatar asked Aug 17 '17 10:08

Dawid Zbiński


People also ask

How to pass data from one component to another in angular?

Using a state object of navigate () the method of Angular router object to pass data between components: Angular allows different ways of passing data between components. We will first learn and demonstrate the state object of navigate () method, this support came since the release of Angular 7.2.

How to pass static data to route in angular?

The Angular can pass data to Route in several ways. We can configure the static data at the time of defining the route. This is done by using the Angular route data property of the route.

How to send a value from Page2 to page1 in angular?

@Input links a property of a component (which is generally the child component) with a value that was given by another component (the parent). import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; It works fine and now, we will define a variable with the @output decorator in order to send a value from page2 to page1.

How to return data from app-Register component in angular?

The app component is a root component generated by Angular itself. We have added app-register component in app.component.html with the properties tableDataValues. Data will return from the app-register component by submitting values. It will hold and pass to a method that is submitted ($event).


Video Answer


1 Answers

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 component isn't supported yet. You can have fun reading this giant issue: https://github.com/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 accomplish 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 component:

    <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.component';
    
    @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);
      }
    }
    
like image 157
Scotty Waggoner Avatar answered Sep 22 '22 01:09

Scotty Waggoner