render: function render(context, partials) {
return this.r(context, partials);
},
Given this code from Twitter's new hogan.js library to demonstrate the issue; what is the goal of naming the function twice?
If it wanted to, the function render would be able to call itself via render(), however, render() is not accessible anywhere else.
Additionally, in a stack trace, you'd see render as the function name, rather than anonymous function.
It's needed for a recursive call.
The first occurance of render is the name of the field the function is stored in, so that you can call the function via
object.render(context, partials);
The second render names the function itself. Debugging tools then display render instead of only function.
A second, possible reason is that the function could call itself recursively.
var render = function render(n) {
console.log("render");
if (n < 1)
render(n + 1);
};
render(0);
Edit: Sorry, I've written something really wrong in the first revision.
Related
I'm new to angular and trying create a custom filter which requires a service. I followed the answer here https://stackoverflow.com/a/43506252/15817005. It solved my issue partially.
Registering filter
angular.module('filters',[]).filter('dataFormat',['studentService', dataFormatFilter])
My Filter factory and filter function.
export function dataFormatFilter(studentService){
console.log(studentService); // Having access here
return dataFormatFunction;
}
function dataFormatFunction(name){
// All the formatting logic
//Need properties from studentService in this function.
}
I am able to access the properties from studentService in dataFormatFilter(factory function). Is there a way to get it in dataFormatFunction.
All the solutions i have seen use dataFormatFunction inside of factory itself dataFormatFilter. But i cannot follows this way.
Thanks!
What it looks like you need to to is return an arrow function that will keep the closure of your filter function so you can use the dependencies without having to pass them around.
I wrote this plunkr to demonstrate.
The critical part being:
const dataFormatFilter = function (studentService) {
return (name) => {
return myReusableFunction(studentService, name);
}
}
app.filter('dataFormat',['studentService', dataFormatFilter]);
Note that the returned value for the function is an arrow function. This isn't the only way to achieve what you are attempting, but should be the simplest.
Hi Guys i'm stuck with a small issue in angular 5, I'm trying to call a common session check method which is imported from a common ts file, i'm using the session check method on load of the page and on click of logout button to redirect the user to login page. but on load of the page it works fine, but on click of a button it gives an error of undefined, Please help thanks in advance.
Dashboard
Imported
this inside function() { ... } definition does not refer to your component, but to that function context. Use arrow function so this context will remain bound to your component:
logout() {
session.signOut().then(() => {
this.s.checkIfSignedIn();
});
}
Also you should remove the var keyword when declaring class variable u.
Bonus advices:
care about your editor/linter warnings (to suppress errors when accessing global objects like gapi, declare that first like this: declare const gapi: any;)
care about code indenting
try to make your variable names descriptive, do not use names like a or u, again so you do not get lost in the code so easily (btw you have utils variable there too, maybe you should use that instead of defining new one called u...)
You are declaring it with var and calling it with this. It's not a property of the component, that's why it's not working.
You have a different scope inside the promise.
logout() {
let self = this;
var session = gapi.auth2.getAuthInstance();
session.signOut().then( function() {
localStorage.clear();
self.s.checkIfSignedIn();
});
}
I'm having trouble updating an array that is displayed as a list. I'm trying to make Vue detect the changes using $set() (as explained in the documentation), but I can't make it work.
Here's my code:
this.choices = this.currentScene.choices;
for (i = 0; i < this.choices.length; i++) {
choice = this.currentScene.choices[i];
choice.parsedText = this.parseText(choice.text);
this.choices.$set(i, choice);
}
Vue still doesn't update the view. What am I doing wrong? Thanks in advance!
Edit: Yes, "this" refers to the Vue instance.
It would definitely be useful to have a JSfiddle of your code, but I'm going to take a crack anyways.
I'm not sure you need to use that function to update the array, since as the documentation points out, its only when you need to change the index of the item.
JavaScript has a built in function called .map that takes a callback function and returns a new array with the callback applied to each item.
For example, you could translate your function to this, assuming that .parseText is a method on the Vue class.
var self = this; // so that we can access the Vue class inside map
this.choices = this.currentScene.choices.map(function(choice) {
choice.parsedText = self.parseText(choice.text);
return choice;
});
And Vue should pick up those changes.
You could use a computed property for this, so you never have to manually update the array. Anytime choices changes you would see the change reflected in this.parsedChoices:
computed: {
parsedChoices: function(){
return this.currentScene.choices.map(function(choice) {
choice.parsedText = this.parseText(choice.text);
return choice;
}.bind(this)); // bind Vue class as value of `this` inside func
}
}
I'm creating a location-based chat app in Meteor. Now I want to render only the chat messages which are in the users region. The TheRegion.region variable gets filled with an HTML5 geolocation request.
Template.locationchat.helpers({
messages: function () {
return Messages.find({location: TheRegion.region});
}
});
The problem of this code is that the TheRegion.region variable is still null when this helper is called. Is there a way to run the helper in a callback of the geolocation function? Or run the template helper when the variable has a value?
I often find in Meteor that if you are waiting on a variable all you need is an if clause to protect yourself.
Try this:
Template.locationchat.helpers({
messages: function () {
if(TheRegion.region)
return Messages.find({location: TheRegion.region});
}
});
It doesn't feel natural, but usually it works. Give it a try.
That's because your variable isn't reactive.
In your onCreated:
TheRegion = new ReactiveDict();
TheRegion.set('region',undefined);
Now, region is always going to exist by the time it reaches the helper & when the value changes, your helper will rerun.
// Main class
function App() {
this.task = new Task(this); // pass the instance of this class to Task so
// it has access to doSomething
}
App.prototype.doSomething = function () {
alert("I do something that Task() needs to be able to do!");
};
function Task(app) {
// This class needs access to App()'s doSomething method
this.appInstance = app;
this.appInstance.doSomething(); // Great, now Task can call the method
}
var app = new App();
The aim of the code above is to give Task access to one of App's methods called doSomething. The code is the current way I'd go about it and I'm posting this to see if it's the best way...
To give Task access I simply pass the whole instance of App, is this efficient or is there a better way to go about it? Is the code above general practice in going about doing something like this?
Yes, what you have is fine. It is a circular dependency, however because of JavaScript's dynamic nature there aren't really any issues.
Another way you could reference App from Task would be a Singleton pattern or something similar, but that would probably be harder to test.
jsFiddle Demo
Generally bind would be used in this scenario assuming that the Task "class" didn't also setup other facilities which were not shown here.
Bind allows for the context to be provided for a function. This could be done in app's constructor. At which point only a function task would be required to call "someMethod".
function task(){
return this["someMethod"]();
}
function App(){
task.bind(this)();
}
App.prototype.someMethod = function(){
alert("Task needed access to this");
};
var a = new App();
However, if task must be a "class", and have other responsibilities then the prototype function could be shared.
function Task(){}
function App(){}
App.prototype.someMethod = Task.prototype.someMethod = function(){
alert("Task needed access to this");
};
var a = new App();
a.task();//->"Task needed access to this"
var t = new Task();
t.someMethod();//->"Task needed access to this"
Your app instances and task instances are tightly bound. App instances have tasks and this can be fine.
A design of loosely coupled objects is more flexible and easier to extend but more complicated to initially create. One such pattern is using a mediator/publish subscriber and have app raise an event/publish message any other object function can listen to this and take action on the event.
For example: your app creates an Ajax instance and when that instance is done it raises some event (fetchedData for example). A listener could be DomDependent.updateView function but later you may want to add/remove/change the order of tasks to do after data is fetched. This can all be configured in a app.init function or per procedure in a controller that kicks of certain procedures (like log in, search, ...).
Instead of creating a whole bunch of specific functions in Ajax (fetchUserPrefs, login, search, ...) you can create one general function and have the controller add listeners or pass the next event when fetchData is complete to run the correct next function.
Here is some pseudo code:
var app = {
init:function(){
mediator.add("updateLogin",domDependent.updateView);
mediator.add("updateLogin",app.loadUserPrefs);
mediator.add("failLogin",domDependent.updateView);
},
login: function(){
mediator.trigger("loadingSometing",{type:"login"});
ajax.fetch({
onComplete:"updateLogin",//what listens to updateLogin you decided in init
onFail:"failLogin",
loginDetails:domDependent.getLogin(),
url:settings.loginUrl,
type:"post"
});
}
}
var ajax = {
fetch:function(data){
data = data || {};
//simple check for onComplete, it's mandatory
var complete = data.onComplete || app.raiseError("ajax.fetch needs onComplete");
//other code to validate data and making ajax request
onSuccess:function(resp){
//mutate data object as the mediator will pass it to
// whatever other function is called next
// you don't hard code domDependent.updateView and
// app.loadUserPrefs because fetch can be used generally and
// success may have to do completely different things after its done
// and you want to define procedures in init, not all over your code
data.response=resp;
//trigger event to do whatever needs to be done next
mediator.trigger(complete,data);
}
}
}
As you can see it gets complicated and maybe doesn't look like code you're used to but it's highly configurable.
I may have misunderstood the advantages of the mediator pattern to loose couple and if so please comment. I use it to:
Make methods more general instead of copying a lot of logic only
because what to do after it's done is different. In fetch the ajax
object just fetches, this would be the same for login or getting
user preferences, the only thing different is what function to call
next/on error when it's done.
A procedure like login involves multiple functions in multiple
objects if this function chain hard code what to do next once a
particular function is done your procedure of login is defined all
over your code. When defining it in init/config you can easily change the
order or add/remove functions in the chain.