ng-include: Access child scope issue - javascript

I'm using DayPilot Scheduler in my app and i'm having the following issue.
home.html:
<div class="container-fluid">
<daypilot-scheduler id="scheduler" daypilot-config="schedulerConfig" daypilot-events="events"></daypilot-scheduler>
</div>
I access daypilot scheduler in my controller like this:
$scope.scheduler;
This works when daypilot directive is directly inside home.html like in home.html above, but returns undefined when I include daypilot with ng-include:
<div class="container-fluid">
<div ng-include src="'partials/partial1.html'"></div>
</div>
partial1.html:
<section>
<daypilot-scheduler id="scheduler" daypilot-config="schedulerConfig" daypilot-events="events"></daypilot-scheduler>
</section>
If it's included with ng-include, $scope.scheduler returns undefined. scheduler is placed under $$childTail as $$childeTail.scheduler.
What am I doing wrong, and how can I access $$childTail?

Try adding $parent. prefix to id attribute's value. So partial1.html will be:
<section>
<daypilot-scheduler id="$parent.scheduler" daypilot-config="schedulerConfig" daypilot-events="events"></daypilot-scheduler>
</section>
And in controller access it like you always did:
$scope.scheduler;

Related

A component is not receiving any of it's #Input values

I use Angular 8 and I have 3 components:
CalculationFirst : app-calculation-first
CalculationSecond : app-calculation-second
CalculationThird : app-calculation-third
CalculationFirst is the "parent" component and has CalculationSecond as a "child" in a way that I use CalculationSecond inside html template of CalculationFirst.
So in CalculationFirst.component.html it looks like this:
<div class="container">
<form #f="ngForm" (ngSubmit)="submit()" novalidate *ngIf="settings.isloaded == true">
<div class="row">
<app-calculation-second [elements]="settings.seconds.elements" [epics]="epics"[types]="types" (opendialoglistevent)="openDialogList($event)"></app-calculation-second>
</div>
</form>
</div>
Then CalculationSecond.component.html looks like this:
<div class="col-lg-2 box">
<div class="row">
<div class="row content" *ngFor="let element of elements;">
<div class="col-lg-14">
<app-calculation-third [elem]="element" [types]="types"></app-calculation-third>
</div>
</div>
</div>
</div>
And finally CalculationThird.component.html looks like :
<div class="col-lg-14">
TEST_TEXT_1
{{elem}}
TEST_TEXT_2
</div>
Now, the problem is if I were to just look at my rendered page, only TEST_TEXT_1 page shows, {{elem}} does not render and neither does TEST_TEXT_2. If I am to check the value of elem, it is undefined. I would expect to get an error that I am trying to display undefined, however I do not get anything. My environment.ts is not set to production, so I do not know if my error is not big enough for angular to inform me. (On a tangent, I don't even get an error if I use a json object in an *ngFor instead of an enumerable (Array), but I'm still not sure if I have some lacking setting).
I have also tried, when I use the third component, to not pass the element from *ngFor but to pass a handmade object {'elemId':0}, this had the same result.
If I move :
<app-calculation-third [elem]="element" [types]="types"></app-calculation-third>
to CalculationFirst, making it a direct child, it works perfectly fine, regardless of what I put in there. Is there a limit to the amount of child components you can have? Am I missing something?
*Edit: Also for those who suggested it is the *ngFor or the usage of different variables, I can make CalculationSecond look like the following and still it doesn't work:
<div class="col-lg-2 box">
<div class="row">
<div class="row content" *ngFor="let element of elements;">
<div class="col-lg-14">
</div>
</div>
</div>
<app-calculation-third [elem]="{ elementId: '' }" [types]="types"></app-calculation-third>
</div>
You are passing the elements to seconds input.
[seconds]="settings.seconds.elements"
But you use elements in your app-second-calculation element.

AngularJs - Using ng-controller with ng-include

This works:
<div ng-include="'login.html'" flex ng-if="!loggedIn" ng-controller="LoginController"></div>
However, this doesn't ({{test}} outputs nothing):
<ng-include src="'login.html'" flex ng-if="!loggedIn" ng-controller="LoginController"></ng-include>
Is there any reason? Or is it a bug?
login.html:
<p>{{test}}</p>
LoginController:
function LoginController($scope){
$scope.test = 'login';
}
I'm not exactly sure where "loggedIn" is defined, but when I define it on a parent controller, both syntaxes work as expected.
Plunkr
<div ng-controller="PrntCtrl">
<div ng-include="'test.html'" flex ng-if="!loggedIn" ng-controller="TestCtrl"></div>
<ng-include src="'test.html'" flex ng-if="!loggedIn" ng-controller="TestCtrl"></ng-include>
</div>
Some questions to consider:
What version of angular are you using?
How is your app defined and how is the controller registered with the app?
Where is "loggedIn" defined?
Because this directive accepts only 3 arguments:
ngInclude | src = string
onload (optional) = string
autoscroll (optional) = string
...according to the ngInclude Docs
EDIT:
you can solve simply wrap it in another element...
<div ng-if="!loggedIn" ng-controller="LoginController">
<div ng-include="'login.html'" flex></div>
</div>

How to use a controller outside of ngApp's scope

Due to the structure of an existing project I'm working on, I'm stuck with a template that looks like this:
<div ng-app="example">
<div ng-controller="MainCtrl" id="inner">
{{ inside }}
</div>
</div>
<div ng-controller="MainCtrl" id="outer">
{{ outside }}
</div>
#outer is supposed to be using the same controller as #inner, but as it's located outside of ngApp's scope, {{ outside }} will not be evaluated. Unfortunately I can't change the template structure, so I tried to compile #outer's content like this:
app.run(function($rootScope, $compile){
$rootScope.$apply($compile(document.getElementById('outer'))($rootScope));
});
This works, but the controller function will be executed twice, which is not desired. Is there a better way to achieve my goal?
Working example on Plunker
what you could do instead, is NOT define ng-app at all in the html, and instead bootstrap angular via javascript.
for example you can do angular.bootstrap(document, ['example']); where 'example' is the angular module for the app for example angular.module('example', [
'ngResource', 'ui.router', ....
]);
you probably defined that yourself already.
This way, you define the ng-app on the entire document scope.
That is normal, you're initializing twice the controller. You could simply create another div, wrapping all the divs you want and use alias. But this will still initialize twice, but each div will have different values, like, {{inside}} on first div will not have the same as the second one has.
<div ng-app="example">
<div>
<div ng-controller="MainCtrl as FirstCtrl" id="inner"> // alias FirstCtrl
{{ inside }}
</div>
</div>
<div ng-controller="MainCtrl as SecondCtrl" id="outer"> // alias SecondCtrl
{{ outside }}
</div>
</div>
But if you intend to use just once the same controller, as far as I'm concerned, you'll have to wrap all divs you want to use the same controller, in just one div, like:
<div ng-app="example" ng-controller="MainCtrl">
<div id="inner">
{{inside}}
</div>
<div id="outer">
{{outside}}
</div>
</div>
This will initialize just once.
Other way, could be attaching ng-app and ng-controller in your html/body tags.

AngularJS controller executes twice (not because of router)

From what I read, the most common cause of this problem is when the controller is included in the template and in the route provider. In my case, only the parent template containing this html is being included in the router, and has its own controller. The sub-templates are being included as a result of a menu selection
So, whenever the menu item is selected, the template gets loaded in, and everything in the controller executes twice. Can it be a product of the the ng-switch or ng-include?
<span ng-switch on="selection">
<div ng-switch-when="0">
<div ng-include="'partials/one.html'" ng-controller="oneController"></div>
</div>
<div ng-switch-when="1">
<div ng-include="'partials/two.html'" ng-controller="twoController"></div>
</div>
<div ng-switch-when="2">
<div ng-include="'partials/three.html'" ng-controller="threeController"></div>
</div>
</span>
Edit:
The included partials do not include the controller again. I've triple checked that these controllers are not mentioned anywhere other than this piece of code. The contents of the one/two/three partials look like this, and the controller still runs twice.
<div>Nothing to see here.</div>
I am making an educated guess here... but does your "'partials/one.html'" also have a ng-controller="oneController" in it? If so, you either need to remove the ng-controller declaration from your include div or from your partial.

Creating complex static Markup with ember.js

I am trying to render my application template, which is getting very complicated, so I want to split it up into separate <script type="text/x-handlebars">'s
I think I want to use the {{view}} helper, but I don't know. Let's say I have this:
<script type="text/x-handlebars" data-template-name="application">
<div id="wrapper" class="clearfix">
<hgroup>
<header>
<div class="logo"></div>
<h1 id="facilityName">{{facilityName}}</h1>
<div id="sessionInfo">
<a id="userName">{{user}}</a>
<a id="logOut" href="../logout">log out</a>
</div>
</header>
</hgroup>
{{view App.breadcrumbsView}}
</div>
</script>
And I want to load this next template inside of the one above:
<script type="text/x-handlebars" id="breadcrumbs">
<div id="breadcrumbs">
<p>
Network
{{#each breadcrumbObj}}
<span>></span><a {{bindAttr href="link"}}>{{name}}</a>
{{/each}}
</p>
</div>
</script>
Right now I am trying to do this with this code from my app.js
App.breadcrumbsView = Ember.View.create({
templateName: 'breadcrumbs',
breadcrumbObj: Util.breadcrumbs()
});
This is not working and I am getting Uncaught Error: assertion failed: Unable to find view at path 'App.breadcrumbsView'
Thanks
I think that you declared your App using var keyword. So it's not visible in handlebars template.
Change this
var App = Ember.Application.create();
To this
App = Ember.Application.create();
And you have to use extend instead of create when creating your views. Because ember will handle the object lifecycle like: create, destroy, add and remove binding etc.
#Marcio is right, you should .extend() and let the framework create it for you automatically by request. Furthermore when you extend the best practice is to use capitalized names like App.BreadcrumbsView.
See here a demo how it renders correctly doing it this way.
Hope it helps.

Categories

Resources