Reputation: 3158
I have this model:
(function(app) {
app.productLine =
ng.core.Component({
selector: 'product-line',
templateUrl: 'templates/sales-product.html',
})
.Class({
constructor: function() {
this.products = [new app.product('101010101010101', '1', '19.99')];
},
addLine: function() {
this.products.push(new app.product('101010101010101', '1', '19.99'));
}
});
})(window.app || (window.app = {}));
(function(app) {
app.product = function (upc, quantity, price) {
this.upc = upc;
this.quantity = quantity;
this.price = price;
return this;
}
})(window.app || (window.app = {}));
However, I can't figure out how to expose addLine()
so I can call it elsewhere.
Logging productLine only shows the constructor:
console.log(app.productLine);
function app.productLine<.constructor()
And calling app.productLine.addLine()
gives TypeError: app.productLine.addLine is not a function.
EDIT:
I found that adding the addLine
function to app.productLine
directly does work. Of course, then the scope of this
is changed, so there needs to be a reference to the constructor's results in a more obvious location.
(function(app) {
app.productLine =
ng.core.Component({
selector: 'product-line',
templateUrl: 'templates/sales-product.html',
})
.Class({
constructor: function () {
this.products = [
{ upc: '',
quantity: '',
price: ''
}
];
app.productLine.products = this.products;
}
});
app.productLine.add = function (upc, quantity, price) {
app.productLine.products.push({
upc: upc,
quantity: quantity,
price: price
});
}
})(window.app || (window.app = {}));
You can then run app.productLine.add(123,456,789);
and the model is updated.
The view, however, is not updated immediately. I believe it is necessary to trigger an update somehow, but with 2-way data binding, if you use the UI to update the model all of the updates appear.
Upvotes: 2
Views: 1330
Reputation: 52867
If you want to expose a shared function that multiple components can use, I suggest implementing a Service and registering it with the application-level injector.
Product Class and ProductService
var Product = ng.core.Class({
constructor: function (upc, quantity, price) {
this.upc = upc;
this.quantity = quantity;
this.price = price;
}
});
var ProductService = ng.core.Class({
constructor: function() {
this.products = [new Product('101010101010101', '1', '19.99')];
},
addLine: function () {
this.products.push(new Product('101010101010101', '1', '19.99'));
}
});
Registering ProductService with the Application-Level Injector
(function(app) {
document.addEventListener('DOMContentLoaded', function() {
ng.platform.browser.bootstrap(app.AppComponent, [ProductService]);
});
})(window.app || (window.app = {}));
Injecting ProductService in Component Constructor and Calling AddLine
(function(app) {
app.AppComponent =
ng.core.Component({
selector: 'app',
directives: [app.ProductLine],
template: '<h1>Anguar 2</h1> <button (click)="addLine()">Add Line</button> <ul><li *ngFor="#product of service.products"><product-line [product]="product"></product-line></li></ul>'
})
.Class({
constructor: [ProductService, function (service) {
this.service = service;
}],
addLine: function () {
this.service.addLine();
}
});
})(window.app || (window.app = {}));
ProductLine directive with Product Input Binding
This directive is used by the parent component.
(function(app) {
app.ProductLine =
ng.core.Component({
selector: 'product-line',
inputs: ['product'],
template: 'UPC:{{product.upc}}<br> Price:{{product.price}}<br>Qty:{{product.quantity}}',
})
.Class({
constructor: function () {
}
});
})(window.app || (window.app = {}));
ProductService
is a singleton. Any component can inject the ProductService
and call AddLine()
and any component that binds to products
will automatically get updated as part of the default change detection strategy.
Upvotes: 1
Reputation: 71961
Have you tried:
var productLine = new app.productLine();
productLine.addLine();
It seems to me that app.productLine
is a class which should be instantiated.
Ah no.. scratch that.. app.productLine is a Component. Never mind me. I only know angular2 in typescript :). I don't think my solution will work, but you can always try. In typescript you don't instantiate components yourself. You just do that by putting them in a template (or using the dynamicLoader
, or the Injector
).
But like I said. I have no idea how to do it in your situation
Upvotes: 0