Pass function from angular1 to downgraded angular2 component - angularjs

Problem:
I am unable to get a function to pass successfully to a downgraded Angular 2 component. I've tried just about every way I can think to pass things in but I am only able to get strings passed in via string interpolation -> some-attribute={{controller.property}}. Here are some of the things I've tried (yes, I know some of them don't make sense...)
some-function="controller.function";
some-function="{{controller.function}}"; //<-- works for data, not functions
[some-function]="{{controller.function}}";
[someFunction]="controller.function";
[(someFunction)]="controller.function";
Setup:
Here is my existing setup which is working for data but not for functions:
Angular 1 usage
<my-component data-input-name="{{controller.name}}"></my-component>
Upgrade/Downgrade adapter
angular.module('myModule').directive('myComponent',
downgradeComponent({
component: MyComponent,
inputs: ['inputName']
}) as angular.IDirectiveFactory);
Angular 2 definition
#Component({
selector: 'my-component',
templateUrl: './my.component.html',
styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {
#Input() inputName: any;
constructor() {}
}
The Angular docs even show how to set it up but they don't give any examples of actual usage.
Am I missing something or can this just not be done?

Use AngularJS kebab case like this, seems to work for me:
<my-component [data-input-name]="controller.name">
</my-component>

Related

Why do ng-if don't work inside a mat-dialog

I have created a mat-dialog component to fire for http response. When I include a ngIf statement inside the html for the mat-dialog,it is not handled. On the console it shows a warning as follows.
Can't bind to 'ngIf' since it isn't a known property of 'div'.
NgIf works fine in all other components in the project.
Calling for mat-dialog inside typescript file.
this.matDialog.open(PaymentModelComponent, {
width: "630px",
data: { message: response.comment },
autoFocus: false,
height: "630px",
});
html code
<div *ngIf="true"><p>Show this only if "show" is true</p></div>
Why do ng-if don't work inside a mat-dialog ?
All I needed to do was to add the DialogComponent to the module's declarations:
declarations: [..., MyDialogComponent]
No need to have the component code in the same file.
All you need to do is add the dialogs to your module imports & declarations. In the same module where the component your dialogs are declared in is declared.
I am posting this hoping that someone may find it useful. This is not the exact answer for this problem, but this is how I overcome my scenario. In my case I was using mat-dialog component as an entry component inside the app.module.ts
entryComponents: [ErrorComponent, UserAccountInfoReloadPopupDialogComponent],
For some reason, ng-if it is not working inside the dialog. It is not only for ng-if, all others like ng-for were not available.
I fixed the issue by defining both components in the same ts file.
#Component({
selector: "app-account-info",
templateUrl: "./account-info.component.html",
styleUrls: ["./account-info.component.css"],
})
export class AccountInfoComponent implements OnInit {
//code
}
#Component({
selector: "user-account-info-reload-popup-dialog",
templateUrl: "./payment-modal.component.html",
styleUrls: ["./payment-modal.component.css"],
})
export class UserAccountInfoReloadPopupDialogComponent implements OnInit {
//code
}
Then I defined the newly created mat-dialog component inside angular module declaration.
#NgModule({
declarations:
[
UserAccountInfoReloadPopupDialogComponent
],
This fixed my issue. You can check the angular mat-dialog documentation.
https://material.angular.io/components/dialog/overview

Downgrade Angular 6 directive to Angular 1.7

I would like to downgrade an angular 6 directive defined something like this
#Directive({
selector: '[ad-host]',
})
export class AdDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
to angular 1.7 but angular https://angular.io/api/upgrade/static module contains downgradeComponent only.
any suggestion how to do so.
the main problem that I am trying to solve is to achieve parent-child communication for children rendered using by the parent and as per https://blog.angular-university.io/angular-ng-content/ blog I can achieve by having inputRef directive.

How to pass down a callback from a parent component to a nested routed component?

I have the following format where I have a global component that has 3 nested components that are activated based on a given route:
$stateProvider
.state('create-goal', {
url: '/create-goal',
component: 'createGoal',
redirectTo: 'create-goal.step-1'
})
.state('create-goal.step-1', {
url: '/step-1',
component: 'step1'
})
.state('create-goal.step-2', {
url: '/step-2',
component: 'step2'
})
.state('create-goal.step-3', {
url: '/step-3',
component: 'step3'
});
Inside of the main create-goal html file, I have the following:
<ui-view goal="$ctrl.goal"
goalInfo="$ctrl.goalInfo"
processStep1="$ctrl.processStep1">
</ui-view>
The goal and goalInfo work great as they are data that is one way data bound. However, when I want to pass down a function, such as processStep1 to compute some action on step-1 and so forth, that function does not show up in the step-1 component even though the goal and goalInfo do.
export default {
name: 'step1',
restrict: 'E',
bindings: {
goal: '<',
processStep1: '&'
},
template,
controller
};
Thoughts?
There a few ways you could go about doing this.
Access the function using $parent (I recommend against this, as it is relative and can cause problems
Pass it down using attributes to inject it into each child function using the '=function' or '&function' depending on your use case
Set the function in a helper service that can be injected anywhere. This is great if you plan on using this a lot and if it is just for data manipulation it really belongs in a service anyways to avoid bloated controllers.
The last way would be use models. This would be good for if it is a function to be run on a certain type of object like users that can easily be modeled. Such as a .save or .update function.
https://docs.angularjs.org/guide/directive
http://fdietz.github.io/recipes-with-angular-js/controllers/sharing-code-between-controllers-using-services.html
https://www.sitepoint.com/tidy-angular-controllers-factories-services/
http://www.webdeveasy.com/angularjs-data-model/

angular1.5 component bind controller once

I am trying to make my first component in angular but i think i am doing it wrong.
In my controller, i call a resource to get data from a web service.
My component look like this :
.component('test', {
templateUrl: '/layout/test.template.html',
bindings: {
data: '='
},
controller: myController
})
i use my component like this in my template :
<test data="row" ng-repeat="row in rowCollection"></test>
The problem is that i call the web service each time i use the component.
In fact, in rowCollection, i have all the data i need. Can i use my component without controller and just use the data passed.
Can you help me ?
thanks
Ok, Writing the problem makes me solve it.
myController was used by my page and my component.
I created a new controler for my component where i don't call the webservice and just use the data passed.
It works well.

Angular 2: when I need a provider section in component?

I tried to search but I didn't get the answer.
I can't realize when I must define "providers" section in #Component definition.
I looked over examples.
half of them use
1)
import { Component, blah-blah} from '#angular/core';
import { SomeService } from './some.service';
#Component({
selector: 'example-selector',
providers: [SomeService ],
.....
constructor(public someService : SomeService ,
2) but half of them WITHOUT "providers" section!
import { Component, blah-blah} from '#angular/core';
import { SomeService } from './some.service';
#Component({
selector: 'example-selector',
.....
constructor(public someService : SomeService ,
===
so, I am confused: when I need that section and when I don't?
I believe Maxouhell gave the right answer in another question:
If you provide your service inside your component, it will be local to it. So if you have two instance of your component, you will have two instance of your service.
Now if you provide your service inside your module, it will be global and if you have two instance of your component, they will share the same instance of the service.
I believe it has to do with at what level you declare your providers. You must declare a provider for each component or service that you use
For example in my app, I have a service that I provide in main.ts which is then available to any component without having to indicate the provider there.
bootstrap(AppComponent,
[
APP_ROUTER_PROVIDER,
HTTP_PROVIDERS,
SettingsService,
disableDeprecatedForms(),
provideForms()
]).catch((err: any) => console.error(err));
#Component({
selector: 'kg-Settings ',
templateUrl: './app/components/settings/settings.component.html',
styleUrls: ['./app/components/settings/settings.component.css'],
directives: [ROUTER_DIRECTIVES, REACTIVE_FORM_DIRECTIVES]
})
However, if I want to inject a component into another component and it has not been previously provided for at a higher level in the app tree,
#Component({
selector: 'k-Calculator ',
templateUrl: './app/components/calculator/calculator.component.html',
styleUrls: ['./app/components/calculator/calculator.component.css'],
directives: [ROUTER_DIRECTIVES, REACTIVE_FORM_DIRECTIVES, Panel, Dropdown, SelectButton, Button],
providers: [CalculationService]
})
You need provider section whenever you need to use a service in that component.
Item #1, defined the provider within the component.
Item #2, (might) defined the provider in app.component.ts (Please check the main file)

Resources