I have a loopback 4 controller with a function that I don't want to expose via HTTP. I would like to be able to call the function from another controller.
How can I do this? Is there any way of injecting a controller in another controller?
(I 'm able to inject repositories in controllers, but not controllers in other controllers).
You have to first import repository of another controller e.g.
import { MemberRepository, EmailTemplateRepository } from '../repositories';
then you have to inject it in constructor like this:-
#repository(EmailTemplateRepository) public emailTemplateRepository: EmailTemplateRepository,
then after you can use any function of controller like this:-
const template = await this.emailTemplateRepository.findOne({
where: {
slug: 'user-password-reset',
status: 1
}
});
Answer is here: https://github.com/strongloop/loopback-next/issues/3028
#inject(‘controllers.AnotherController’) c: AnotherController
Ok I figured out how to make this work. You have to import the #repository component where the rest of the other import statements are, like so:
import { repository } from '#loopback/repository';
Adding this, will allow for, #repository(EmailTemplateRepository) public emailTemplateRepository: EmailTemplateRepository, to work.
Related
I have been searching for certain feature we use in Laravel to specify where the routes will go in controllers methods like so:
Route::get('/user', 'UserController#index');
In above code when user navigate to /user the app will send him to the UserController and directly into index method.
I'm looking for something similar to help me handle delete routes because I want to restrict them for super admins only and don't want to write additional component for that
You need to use middleware for that. For example:
Route::get('user/{id}/delete', 'UserController#delete')->middleware('superadmin');
AFAIK this is not possible directly with Angular where as you can do this
Send some data with the router like
{path : 'heroes', component : HeroDetailComponent, data : {some_data : 'some value'}}
And in the component onInit check for the data using ActivatedRoute
and assign it to the proper method of the compoenent
Update
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.sub = this.route
.data
.subscribe(v => console.log(v));
}
I have added a class like this.
export class Settings{
public data: string = "blopp";
}
When I try to access the data, it seems that the field I'm trying to assign that value to sees the class Settings itself but it doesn't recognize the data thingy.
How do I redesign the class to provide settings for other components?
I've read about #Output decorator but since I won't be binding to the values, it seems not the correct approach. I've made sure that the class is imported and recognized withing the component that's supposed to consume it. I've also tried the corresponding exposure but using a function in the class with settings - the same, failed result.
If you're using angular-cli and going to store in this class environment specific settings - you already have built in support for this.
Put the setting into environment.ts. For example:
export const environment = {
production: false,
someSetting: 'foo',
};
Then it can be consumed from anywhere within the app:
import { environment } from "../environments/environment"; //fix according to your project structure
#Injectable()
export class SampleService {
private foo = environment.someSetting;
}
Here you can find more info on how to add more environments and build you project with specific environment settings.
Your best bet for storing global settings is to use a service. The code for that looks like this:
import { Injectable } from '#angular/core';
#Injectable()
export class DataService {
serviceData: string;
}
I have a blog post about this here: https://blogs.msmvps.com/deborahk/build-a-simple-angular-service-to-share-data/
And a plunker here: https://plnkr.co/edit/KT4JLmpcwGBM2xdZQeI9?p=preview
Also, the #Output decorator is only for communication between a child component and a parent component where the child is nested within the parent.
I have alert service in a angular 4 project. All components can set alerts in that service, but only some show them and each one shows them in a unique location.
So my question is how is it possible to define get a variable from a service in all the html files?
My service looks like this:
import { Injectable } from '#angular/core';
#Injectable()
export class AlertService {
message;
constructor() { }
setMessage(message){
this.message = message;
}
}
And the component that wants to set a message just imports the service and calls setMessage method. But when i try to use message in html file like:
{{message}}
then its out of scope. How can i make this message accessible in all html files of all components?
Or maybe there is a better way to solve this kind of an requirement than a service variable?
In order to consume the message in your component you need to inject the service in your constructor (which you are probably doing).
Component:
export class MyComponent {
constructor(public alertService: AlertService)
In the markup reference alertService.message instead of message.
{{ alertService.message }}
I wonder what is the right way to use http service. For example all my requests to server starts with /Api.
Should I write this.http.get('/Api/SomeRoute/:id') every time, or more elegant way exists to omit Api?
Or should I create some other managerService which will use http?
Something like an endpoint url is probably a good example for a general configuration file.
In my angular 2 apps i use the dependency injection for it. In this case i have something like an app.config.ts using OpaqueToken to make it injectable:
import { OpaqueToken } from '#angular/core';
export interface IAppConfig {
appTitle: string;
endpointUrl: string;
};
export const CONFIG: IAppConfig = {
appTitle: 'MyApp',
endpointUrl: 'http://api.myrealservice.com/'
};
export const LOCALCONFIG: IAppConfig = {
appTitle: 'MyApp (LOCAL)',
endpointUrl: 'http://localhost:8080/api/'
};
export let APP_CONFIG = new OpaqueToken('app.config');
This way you can have several configs (for example for local development or production etc..) and define this as a provider in your module like this:
providers: [
...,
{
provide: APP_CONFIG,
useValue: CONFIG
},
...
]
Then i just inject this config wherever i may need it, for example in a backend service to use the endpointUrl:
...
constructor(#Inject(APP_CONFIG) private _config:Config) {
console.log(this._config.endpointUrl);
}
In your module you can just change the kind of Config you want to provide (in this example CONFIG or LOCALCONFIG for example) and don't have to change it anywhere else anymore.
Hope this helps.
After your edit, you added a second question Or should I create some other managerService which will use http?:
Short answer: yes. You should seperate logic of your components, services, etc. as much as possible.
Let's say you have a an API which serves information about cats and dogs. What you want to have in your frontend would probably be a CatService, a DogService and a BackendService or ApiService, whatever you want to call it.
The CatService and DogService are the ones your view components will interact with, for example they will have methods like getCatById() or something like that. These services will most likely interact with anohter service, the BackendService which will inject Http and use general methods like post(), get() and so on.
So your BackendService is the one who has to know the specific urls, handle the responses or errors and report back to the calling services with the results, while the other ones will just be used as a pipeline and handle specific business logic.
You are right, it is better to put repeating values in a variable. You can put the base URL in a const:
const apiUrl = '/Api/';
and then if there is a change to the URL, you only change it in one place, and also your code looks cleaner. The usage is like this:
this.http.get(apiUrl + 'SomeRoute/:id')
Of course you can also create a function that does that for you, but that may be too much abstraction.
I have a form that transitions through several views. Currently each controller.js file has a long list of these Ember.computed.alias. How can I break that out into one file and import it into each controller?
Currently in each controller.js
entityEmail: Ember.computed.alias('controllers.checkout.entityEmail'),
entityDOB: Ember.computed.alias('controllers.checkout.entityDOB'),
entityPhone: Ember.computed.alias('controllers.checkout.entityPhone'),
entityAddress1: Ember.computed.alias('controllers.checkout.entityAddress1'),
entityAddress2: Ember.computed.alias('controllers.checkout.entityAddress2'),
entityCity: Ember.computed.alias('controllers.checkout.entityCity'),
I would like to pull all that out into a file so I can simply import some 1 liner in each controller.js
This is a classic use-case for Ember.Mixin.
You can extract all these computed props into a single mixin and extend every controller (that needs to have these props) with it.
Add the following mixin to your app
// app/mixins/entity-form.js
import Ember from 'ember';
const { Mixin, inject, computed: { alias } } = Ember;
export default Mixin.create({
checkout: inject.controller(),
entityEmail: alias('checkout.entityEmail'),
entityDOB: alias('checkout.entityDOB'),
entityPhone: alias('checkout.entityPhone'),
entityAddress1: alias('checkout.entityAddress1'),
entityAddress2: alias('checkout.entityAddress2'),
entityCity: alias('checkout.entityCity')
});
And then use it in a controller
// app/controllers/example.js
import EntityFormMixin from 'yourAppName/mixins/entity-form';
const { Controller } = Ember;
export default Controller.extend(EntityFormMixin, {
// rest of controller's props and functions
});
Note: Ember.inject API is available since Ember 1.10.0. In case you are using an older version you need to replace the inject line with: needs: ['checkout'] and prefix the aliases with "controllers." like you did in your example.