The thing i'm trying to do, is to inject owner to my JS native class in Ember(3.15.0).
It looks something like this:
component.ts
export default class ClassOne extends Component {
constructor() {
super(...arguments);
const myClass = new ClassTwo();
...
}
}
ClassTwo.ts
export default class ClassTwo {
#service() someService: ServiceType;
...
}
Because of that, on someService, i'm getting expectable Attempting to lookup an injected property on an object without a container, ensure that the object was instantiated via a container
I've seen similar questions that were solved by using getOwner(this).ownerInjection() but those were all based on Class.create() that was extended by Ember.Object.
Is there any way to do that?
Thanks in advance for any help.
The way to do this in modern Ember is to use setOwner.
import { setOwner } from '#ember/application';
import { inject as service } from '#ember/service';
export default class MyClass {
#service myService;
constructor(owner) {
setOwner(this, owner);
this.appName = this.myService.appName;
}
}
See it working here: https://ember-twiddle.com/e6481c33c3150e3418606e79decaed78?openFiles=classes.my-class%5C.js%2C
See documentation for setOwner here:
https://api.emberjs.com/ember/3.22/functions/#ember%2Fapplication/setOwner
This answer should work in Ember 3.15+ and is current as of Ember 3.23.
By the way, that error message could really use an update from container -> owner
Related
I am looking at a user service, my understanding is it's similar to a user service in Nest, but not really.
In it I see the following:
export class UsersService {
private usersDao: UsersDao
constructor() {
this.usersDao = UsersDao.getInstance();
}
}
static getInstance(): UsersService {
if (!UsersService.instance) {
UsersService.instance = new UsersService();
}
return UsersService.instance;
}
What is that getInstance() doing exactly? And why not just:
export class UsersService {
constructor(private usersDao: UsersDao) {}
}
What is the goal of getInstance()?
Usually this is part of the singleton pattern. Basically one class that, once instantiated, any subsequent classes will refer to that instance, rather than creating a fresh instance each time.
https://en.wikipedia.org/wiki/Singleton_pattern
Its useful for a class where something complex needs to happen when it is first constructed, but all following calls just need access to the properties.
I'd also like to mention that you can (in JavaScript specifically) export an instance, and all modules that import the module will have access to the same instance.
I have three classes : User, Account, and Model. User and Account are extending Model class.
User.js :
import Model from '#/classes/Model'
export default class User extends Model {
constructor(data) {
super(data)
}
}
Account.js :
import Model from '#/classes/Model'
export default class Account extends Model {
constructor(data) {
super(data)
}
}
And Model.js :
import Account from '#/classes/Account'
import User from '#/classes/User'
export default class Model {
static _classesMapping = {
Account,
User
}
constructor(data) {
...
}
static create(models) {
return new Model._classesMapping[this.name](models)
}
}
I want to create Account and User instances from the static method create in Model like this : Account.create()
However, i get this error when compiling: "Super expression must either be null or a function" because of the circulary dependecy issue.
I don't know how i can solve this issue without having to passing the class as an argument to the Model.create method like this, which i find ugly
Account.create(data, Account)
I want to create Account and User instances from the static method create in Model like this: Account.create()
Well, you don't need any _classesMapping for that. You can simply access the constructor by this, you don't need to go look it up by its name.
// Model.js:
export default class Model {
constructor(data) {
…
}
static create(models) {
return new this(models)
}
}
That solves your circular dependency problem by simply removing the dependency :-)
I think the best way to solve this is to move your classesMapping to an external file.
So you get
Model.js
User.js
Account.js
ClassMapping.js
Which imports User and Account and is imported by Model.js
I am new to Aurelia, but am working on an existing project and learning as I go.
I want to add a javascript class file and have NPM include it in the build, but I cannot find clear documentation on how to do that.
It is not a complex class and does not require an html template.
Just add the .js file containing your class to your src folder and add the following to import it in the file you intend to use the class.
import * as MyClass from './my-classs';
following the convention, you can create a class with the below...
export class MyClass {
myProperty = 'foo';
myOtherProperty = { key:'value' };
constructor() {
// constructor stuff (optional of course)
}
myMethod() {
// do something
}
}
Then in your ViewModel, for example...
import { inject } from 'aurelia-framework';
import { MyClass } from 'path/to/my-class';
#inject(MyClass)
export class MyViewModel {
constructor(myClass){
this.myClass = myClass;
}
attached() {
console.log(this.myClass.myProperty);
this.myClass.myMethod();
}
}
The way you import your class does depend on whether it's written as a module or not. If it's not a module, you'll have to write it out as #john-little mentioned.
The MyClass will automatically be a singleton until you make it transient (see https://aurelia.io/docs/fundamentals/dependency-injection#object-lifetime-child-containers-and-default-behavior)
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 am new to Javascript and TypeScript and I am wondering if it is possible to do some kind of dependency injection (maybe using require.js)
I have two classes in same module
module MyWebApp {
export class ViewRouter {
... some class methods
}
}
module MyWebApp {
export class MyViewModel{
private router: ViewRouter;
constructor(router:ViewRouter router) {
this.router = router;
}
}
}
Every time I need MyViewModel I have to instantiate ViewRouter
var vm = new MyViewModel(new ViewRouter());
Is there any way around this? I thought that Require.js could help me solve my problem but I don't know how to use it with TypeScript.
Thank you.
If you want a new instance every time you should probably do:
class MyViewModel{
private router: ViewRouter;
constructor() {
this.router = new ViewRouter();
}
}
Now if you want a "single" shared instance you can do:
module MyWebApp {
export class ViewRouter {
... some class methods
}
export var router = new ViewRouter();
}
and use router
Using RequireJS can do the same thing for your, but the principal idea will not change there. RequireJS is not an IOC container.
There are bunch of javascript IOC containers out there and I don't have a recommendation on that : Google search