Angular 2 iframe для родительской связи

в моем текущем проекте у меня есть несколько приложений Angular 2, которые должны обслуживаться приложением портала (также Angular 2). Таким образом, приложение портала имеет область заголовка со ссылками на все базовые приложения. Когда пользователь нажимает на одну ссылку приложения, соответствующее угловое приложение загружается в фрейм тела портала.

enter image description here

Сейчас я разрабатываю центральную службу авторизации. На портале у меня есть сервис, который хранит права текущего вошедшего в систему пользователя. У меня вопрос: возможно ли получить доступ к угловым 2 службам/компонентам родителя (портала) в отдельных приложениях (iframe)? Казалось, что это возможно в угловом 1 через прицел

Ответ 1

Сейчас я пытаюсь сделать нечто похожее (приложение портала с вложенными приложениями в iFrame). Вы можете обмениваться данными между вашим сервером и клиентом (в любом направлении), используя window.postMessage для отправки данных.

Так, например, на сервере приложения:

var iframe = document.getElementById('useriframe');
    if (iframe == null) return;
    var iWindow = (<HTMLIFrameElement>iframe).contentWindow;

    iWindow.postMessage({"for":"user","data":"anything"}, 'http://localhost:4001');

и в клиентском приложении (размещенном в iFrame)

export class AppComponent {

@HostListener('window:message',['$event'])
onMessage(e)
{
if (e.origin!="http://localhost:4200")
  {
  return false;
  }
if (e.data.for=="user")
  {
  alert('here i am');
  }
}

Отображение маршрутов дочерних фреймов в родительском элементе Итак, в моей реализации мы передаем токены и пользовательскую информацию из приложения оболочки в дочерний iFrame и передаем информацию о маршрутизации из дочерних приложений обратно в оболочку, чтобы URL отражал маршрут, выбранный в дочернее приложение. В дочернем приложении у вас может быть маршрут, такой как:

[Userapp]/edituser/имя пользователя

и мы хотим опубликовать его в родительском приложении и отобразить маршрут следующим образом:

Http://МойВебСайт/главная/программа/пользователь # edituser/боб

Обратите внимание, что мы используем хэштег для маркировки дочернего маршрута, а в ваших дочерних приложениях вы перехватываете каждое навигационное событие и публикуете новый маршрут через

export class MyRoutingComponent implements OnInit {
constructor(private router: Router) { 
router.events.subscribe((event: Event)=>{
  if (event instanceof NavigationEnd){
        let url=(<NavigationEnd>event).url;
        if (url.length>1)//don't post message about base route '/'
          window.parent.postMessage({"for":"dashboard", "operation":"changeroute","route":url},'*')
  }

})
}

а затем в родительском приложении проанализируйте сообщение и используйте его для обновления отображаемого пути к местоположению.

    url = url +'#' + route;            
    this.location.go(url);

Ответ 2

Привет, я действительно ценю решение, данное @jazza1000, оно мне помогло.

Наша проблема заключалась в том, что в текущей (на сегодняшний день) версии angular cli есть ошибка, которая не позволяет использовать внешние файлы JS даже с allowJs. Мы будем использовать jsplumb (внешний js) для представления некоторых блок-схем. (Актуальная проблема)

Поэтому мы решили пойти с подходом размещения функциональности, которая использует внешний JS в дополнительном угловом приложении. И родительское приложение angular 5 принесет приложение angular 4 с iFrame. Поэтому, когда пользователь захочет просмотреть потоковую диаграмму, мы откроем приложение angular4 в iframe, после чего он нажмет кнопку "Сохранить" в приложении angular 4, которое сохранит все его модификации, после чего отправит сообщение в родительское окно, которое закроет/скроет div с iframe.

Наше родительское приложение в angular 5 имеет код

 @HostListener('window:message', ['$event'])
  onMessage(e) {
    debugger;
    if (e.origin != "http://localhost:4201") { // set your origin
      return false;
    }
    if (e.data.for == "user") {
      alert('here i am');
    }
  }

Наше приложение iFrame angular 4 для кнопки сохранения имеет код (мы запускаем приложение с --port 4201)

window.parent.window.postMessage({"for":"user","data":"anything"}, 'http://localhost:4200')