createOptionsFromRemotingContext globally - loopbackjs

Is there an option to specify this method globally so it will affect all the models or i need to specify it for every model i want to use it?
Customer.createOptionsFromRemotingContext = function(ctx) {
var base = this.base.createOptionsFromRemotingContext(ctx);
return extend(base, {
headers: ctx.req.headers,
});
};

I think this can be done with mixins:
https://loopback.io/doc/en/lb3/Defining-mixins.html
https://github.com/strongloop/loopback-example-mixins

Related

How to refactor {{link-to}} helper into a function that can be used in transitionTo?

I currently use a {{link-to}} helper that was written by someone else to explicitly state the query params to pass to the next route and strip out others that are not stated. It looks like this:
//link-to example
{{#link-to 'route' (explicit-query-params fromDate=thisDate toDate=thisDate)} Link Text {{/link-to}}
//the helper
import {helper} from '#ember/component/helper';
import Object from '#ember/object';
import {assign} from '#ember/polyfills';
export function explicitQueryParams(params, hash) {
let values = assign({}, hash);
values._explicitQueryParams = true;
return Object.create({
isQueryParams: true,
values,
});
}
export default helper(explicitQueryParams);
// supporting method in router.js
const Router = EmberRouter.extend({
_hydrateUnsuppliedQueryParams(state, queryParams) {
if (queryParams._explicitQueryParams) {
delete queryParams._explicitQueryParams;
return queryParams;
}
return this._super(state, queryParams);
},
});
I've recently had a use case where I need to apply the same logic to a transitionTo() that is being used to redirect users from a route based on their access:
beforeModel() {
if (auth) {
this.transitionTo('route')
} else {
this.transitionTo('access-denied-route')
}
},
I am really struggling to see how I can refactor what I have in the handlebars helper to a re-usable function in the transitionTo() segment. I'm even unsure if transitionTo() forwards the same arguments as {{link-to}} or if I will have to fetch the queryParams somehow from a different location.
Any insight would be greatly appreciated.
Well first off, tapping into private methods like _hydrateUnsuppliedQueryParams is risky. It will make upgrading more difficult. Most people use resetController to clear stick query params. You could also explicitly clear the default values by passing empty values on the transition.
But, ill bite because this can be fun to figure out :) Check this ember-twiddle that does what you're wanting.
If you work from the beginning in the transitionTo case, we can see that in the router.js implementation:
transitionTo(...args) {
let queryParams;
let arg = args[0];
if (resemblesURL(arg)) {
return this._doURLTransition('transitionTo', arg);
}
let possibleQueryParams = args[args.length - 1];
if (possibleQueryParams && possibleQueryParams.hasOwnProperty('queryParams')) {
queryParams = args.pop().queryParams;
} else {
queryParams = {};
}
let targetRouteName = args.shift();
return this._doTransition(targetRouteName, args, queryParams);
}
So, if the last argument is an object with a query params obj, that's going directly into _doTransition, which ultimately calls:
_prepareQueryParams(targetRouteName, models, queryParams, _fromRouterService) {
let state = calculatePostTransitionState(this, targetRouteName, models);
this._hydrateUnsuppliedQueryParams(state, queryParams, _fromRouterService);
this._serializeQueryParams(state.handlerInfos, queryParams);
if (!_fromRouterService) {
this._pruneDefaultQueryParamValues(state.handlerInfos, queryParams);
}
}
which has the _hydrateUnsuppliedQueryParams function. So, to make this all work, you can't share the function directly from the helper you've created. Rather, just add _explicitQueryParams: true to your query params. Job done :)
The link-to version is different. The query params use
let queryParams = get(this, 'queryParams.values');
since the link-to component can take a variable number of dynamic segments and there needs to be some way to distinguish between the passed dynamic segments, a passed model, and query params.

Observe change on any attribute of an Ember Data

Is this possible? Something like .observes('_data'), but not.
The use case is, I have a Decays mixin that has some CPs that say how long its been since a model has been updated. I'd like these CPs to be able to update if any of the model's attrs have changed. isDirty also won't work, since my use case uses store.push to update the model.
I don't think there's a built-in way to do it, but it wouldn't be very difficult to make one. Just create a base class for all of your models and override the set function. Something like this:
var BaseModel = DS.Model.extend({
set: function(keyName, value) {
var ret = this._super.apply(this, arguments);
var attributes = Ember.get(this.constructor, 'attributes');
if (attributes[keyName]) {
this.trigger('attributeChanged');
}
return ret;
}
});
Then, you can listen for changes to any attribute like this:
model.on('attributeChanged', function() {});
I think you can even do something like this in the case of a controller or similar object (although I haven't tested it):
Controller.extend(Ember.Evented, {
modelPropertyChanged: function() {
}.on('model.attributeChanged')
});

Meteor.js - Calling a template helper within template rendered

I'm using Meteor 1.0.
I have a Template.*name*.rendered function that makes a number of calculations. At the end of the calculations, I would like the output to make its way into a Template.*name*.helpers so I can use it in the corresponding html page.
Here's a simplified version of the code:
Template.myTemplate.rendered = function () {
var x = Math.random();
Template.otherTemplate.helpers({
randomNum: x
});
}
When I call {{randomNum}} in otherTemplate, nothing happens.
I have also tried putting the Template.*name*.helpers outside of Template.*name*.rendered, in which case, I get the error:
Uncaught ReferenceError: x is not defined
Thoughts?
This isn't really the right way of going about things as the way Meteor works is by compiling templates before the application starts, rather than at run-time. Whilst something along these lines may be possible (for example by using Template.registerHelper), it would be much better to set a reactive variable to a specific value in the rendered callback and have the helper set to return that instead:
Session.setDefault('randomNum', 0);
Template.myTemplate.rendered = function () {
Session.set('randomNum', Math.random());
}
Template.otherTemplate.helpers({
randomNum: Session.get('randomNum')
});
If you'd rather use a private variable for the randomNum, have a look at ReactiveVar. It could be any reactive data source and it would work.
You used to create helpers as an object of the template but since Meteor has deprecated that you now have to create the helpers within the helper function.
Now in order to call the helper via javascript you must use this function
Template.*TemplateName*.__helpers.get('*HelperName*')(*Params*);
Its a pretty simple way of doing this and it keeps the functions out of the global scope so its pretty clean.
Here is an example of how I am using this
~~~
Template.home.events({
'click .pair': function(event) {
var _this = $(event.currentTarget);
Template.home.__helpers.get('pairDevice')(_this);
}
});
Template.home.helpers({
'devices' : function() {
return Session.get('devices');
},
'pairDevice' : function(elm) {
elm.fadeOut();
$('.home-page').addClass('paired');
var deviceList = [
{
'name' : 'Patrick\'s Phone',
'UUID' : '234123,4n123k4nc1l2k3n4 l1k23n4l12k3nc4l12'
},
{
'name' : 'Mike\'s Phone',
'UUID' : '734k23k4l2k34l2k34l2k34l2k3m'
},
{
'name' : 'Edgar\'s Phone',
'UUID' : '567k56l7k4l56k7l5k46l74k56l74k5'
}
];
Session.set('devices', deviceList);
}
});
~~~

EmberJS Inheritance Conundrum

Consider this situation. I have a common logic which I want to reuse across Ember.ArrayController and Ember.ObjectController instances.
Both Ember.ArrayController and Ember.ObjectController are derived from a basic Ember.Object so I am trying something like:
AbstractController = Ember.Object.extend({
// some methods with common logic
});
AbstractArrayController = AbstractController.extend({});
AbstractObjectController = AbstractController.extend({});
The problem is I also need AbstractArrayController and AbstractObjectController to extend from their parents (Ember.ArrayController and Ember.ObjectController).
How would I achieve this sort of inheritance?
I am looking at reopen and reopenClass methods right now, maybe they could be useful: http://emberjs.com/api/classes/Ember.Object.html#method_reopen
I tried just doing something like:
Ember.Object.reopenClass({
foo: function () {
return "foo";
}.property("foo")
});
But that doesn't seem to work.
Another way to put the problem:
App.HelloController = Ember.ObjectController.extend({
foo: function () {
return "foo";
}.property("foo")
});
App.WorldController = Ember.ObjectController.extend({
foo: function () {
return "foo";
}.property("foo")
});
How to abstract the foo computed property?
reopenClass adds methods on the class object, not the instance objects. When you do:
Ember.Object.reopenClass({
foo: function () {
return "foo";
}.property("foo")
});
You are creating Ember.Object.foo().
You need to use reopen if you want to methods at an instance level, for example Ember.Object.create().foo().
To answer you question, the best way to abstract a function that many types of objects can use is with a mixin. To create a mixin you use.
var mixin = Ember.Mixin.create({
foo: function() {
return 'foo';
}
});
And to have your objects take advantage of that mixin you can use.
var MyController = Ember.ObjectController.extend(mixin, {
// ...
});
More about mixins: http://codingvalue.com/blog/emberjs-mixins/ and http://emberjs.com/api/classes/Ember.Mixin.html

How to create private method/property in Ember.Object?

We can create Em.Object like this:
var foo = Em.Object.create({
somevar : '123'
});
and then use it:
foo.get('somevar');
but how to create a private property or method in Em.Object which would be accessable from the object but wouldnt be ourside?
There is indeed a way to have private variables in Ember objects, as follows:
MyObject = Ember.Object.extend({
init: function() {
// private variable
var a = 1;
// methods to get, set, or otherwise accesss the private variables
this.getA = function() {return a;};
this.setA = function(val) {a = val;}
// don't forget this!
this._super(...arguments);
}
});
now try
o1 = MyObject.create()
o2 = MyObject.create()
o1.setA(42);
o2.getA(); //1
In other words, you have to declare the private variables, AND any getters, setters, or other routines that want to use them, in the init hook. Of course, this means that those getters/setters will be present on each instance of the class, rather than in its prototype. That's slightly inefficient, but the same holds for any approach to private variables for classes in JavaScript.
It is conceivable that Ember could introduce a new private: {} hash on objects, but then Ember would need a lot of machinery to handle finding and controlling access to private variables across class hierarchies. It would be equivalent to redesigning or extending the language itself, which is not part of the Ember mission.
Meanwhile, the above approach works fine if the number of private instance variables is limited and the number of routines that need to access them is small. So the accepted answer that says this is impossible is, well, wrong.
It's not possible, since Ember.js does not provide any encapsulation mechanisms.
However, you can simply use some convention for private members. For example, prefix them with _ sign.
You could use a closure:
(function() {
var somePrivateProperty = 'xyz';
MyObject = Em.Object.extend({
someComputedProperty: function() {
return 'somePrivateProperty = ' + somePrivateProperty;
}).property()
})
})();
Is possible with a little trick:
var obj = Em.Em.Object.create(
new function(){
var privateVar = "this is private";
this.getPrivateVar = function(){
return privateVar ;
}
},
{
emberVar: "Ember var",
emberMethod : function(){
return this.getPrivateVar();
},
emberMethod1 : function(){
return privateVar ;
},
emberBinding : 'emberVar'
}
)
now if U try to get private var
obj.privateVar
> unknown
obj.getPrivateVar()
> "this is private"
obj.emberMethod()
> "this is private"
The only problem is that:
obj.emberMethod1()
> unknown