How to update Array In Vue.js using method? [duplicate] - javascript

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
I Can't Update my array using methods in Vue.js !
<script>
import Vue from 'vue';
export default {
data () {
return {
from:'',
to:'',
places:[]
}
},
methods:{
searchFrom:function(){
var autoComplete = new google.maps.places.AutocompleteService();
autoComplete.getPlacePredictions({input:this.from},function(data){
this.places=data;
});
}
},
computed:{
}
}
</script>
<style>
</style>
This throws an error on console: "Uncaught TypeError: Cannot read property 'places' of undefined"

This is because you're not using fat arrows, change the code to:
methods:{
searchFrom (){
var autoComplete = new google.maps.places.AutocompleteService();
autoComplete.getPlacePredictions({input:this.from}, data => {
this.places=data;
});
}
},
In more details:
when you call autoComplete.getPlacePredictions it uses a callback, and in that callback the this context is changed and is no longer Vue context, so it does not know what this.places is. Fat arrow (=>) takes care of it and makes sure that the context remains the same.

I've never had good luck using fat arrows in Vue. The this is not what you expect. Try explicitly assigning this at the start of your searchFrom() method, like this...
methods:{
searchFrom (){
var me = this;
var autoComplete = new google.maps.places.AutocompleteService();
autoComplete.getPlacePredictions({me.from}, data => {
me.places=data;
});
}
}

Related

Can you set a function inside an object in chrome.storage.local?

Im building a chrome app and I am trying to add a function inside an object inside chrome.storage.local but when im doing it it does not appear if you try to get it (all the other things appear but not the function)
But if you try to do it on a normal object like
let a = {
b: function() {
return 'This is working'
}
};
then it works.
It wouldn't be a problem if I could just use eval but due to security on the chrome app it does not work.
What im trying to do is:
chrome.storage.local.set({
'obj': [{
example: 'hello',
fn: function() {
return 'This is not working'
}
}]
});
Then if you do
chrome.storage.local.get('obj', function(e) {
console.log(e.obj)
});
Then it will return with
Array (length 1): example: "hello"
and not the function,
Thanks.
Store arguments and the body like this
{function:{arguments:"a,b,c",body:"return a*b+c;"}}
Retrieve it and instantiate the function:
let f = new Function(function.arguments, function.body);

Cannot set property 'weather' of undefined [duplicate]

This question already has answers here:
What is the use of the JavaScript 'bind' method?
(23 answers)
Closed 3 years ago.
Putting Json data in a this.variable but I keep getting the error Uncaught (in promise) TypeError: Cannot set property 'weather' of undefined. Does anyone know how to fix this.
var currentWeather;
function setup() {
createCanvas(400, 400);
currentWeather = new CurrentWeather();
currentWeather.create();
loadJSON(currentWeather.api, currentWeather.gotData);
}
function draw() {
background(0);
}
///////////////////////////////////////////////////////////////////
class CurrentWeather{
create(){
let url = 'https://api.openweathermap.org/data/2.5/weather?q=';
let city = 'Manassas';
let apiKey ='ApiKeyHere';
let units = '&units=imperial';
this.api = url + city + apiKey + units;
this.weather;
}
gotData(data){
this.weather = data;
}
}
Try to change this line loadJSON(currentWeather.api, currentWeather.gotData); to
loadJSON(currentWeather.api, currentWeather.gotData.bind(currentWeather));
You are having scoping issues. this is being overridden/lost from your callback methods. In your case this supposed to be the instance of CurrentWeather which you have as currentWeather = new CurrentWeather();. .bind(currentWeather) is used to scope this to a specific function. Also since the currentWeather is defined globally you may need to just use that variable instead of using this in some cases. It's hard to tell where other issues are without the full code.

How do you (best) access 'this' in an object method passed as callback [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I'm writing a simple word game to practice my javascript (I'm new to it) using the NPM package prompt (https://www.npmjs.com/package/prompt) to query the user when I need a response.
Since I come from an OOP background (in other languages) I've been experimenting with encapsulating different functionalities in different objects. So I have all the prompt related code in one object, like this
function Prompter() {
this.getUserName = function (callback) {
var schema = {
properties: {
name: {
description: "Tu nombre por favor:",
pattern: /^[ñÑa-zA-Z\s\-]+$/,
message: 'Solo letras, por favor',
required: true
}
}
};
prompt.get(schema, callback);
};
}
and game logic in another object like this (this is the relevant part of the code)
function Game() {
this.qGenerator = null;
this.prompter = null;
this.user = "";
this.doNextRound = function () {
//// omitted for brevity
};
this.init = function () {
this.qGenerator = new QuestionGenerator();
this.prompter = new Prompter();
};
this.startGame = function () {
this.prompter.getUserName(this.storeUserName);
};
this.storeUserName = function (err, result) {
if (err) {
this.handleErr(err);
return;
}
this.user = result.name;
this.doNextRound();
};
}
and I start the game like this
const game = new Game();
game.init();
game.startGame();
The problem I have is that in the Game method storeUserName, which I've passed as a callback to prompt, I have no access to the Game object through this, and thus, when I call
this.doNextRound
inside of storeUserNameI get
TypeError: this.doNextRound is not a function
I understand why, as this refers to Node inside the callback. But I don't know how to keep a reference to the correct this inside the method I'm passing as callback. I understand how to do it in more 'vanilla' Javascript -- using that = this, or apply,etc, but I'm not sure what the best way to handle this inside Node callbacks is when you're passing another object's methods. Any advice much appreciated.
Use Function.prototype.bind:
this.prompter.getUserName(this.storeUserName.bind(this));
or an arrow function:
this.prompter.getUserName( _ => this.storeUserName() );
Either of those will work.

Reactive variable is undefined when it is defined

I would like to get some help debugging a situation where a Reactive Variable is undefined, when it has been defined already.
This code is attaching a Reactive Variable to the template instance, and using the variable in template.autorun().
Template.home.onCreated(function () {
this.limit = new ReactiveVar(15);
this.autorun(function () {
this.subscribe('recent-topics', this.limit.get());
});
});
When I load the template for the first time, I expect the template to subscribe to recent-topics with an argument 15. However, the code throws an error:
Uncaught TypeError: Cannot read property 'get' of undefined
Any ideas why?
Just an answer for the sake of spreading the joys of ES6:
Template.home.onCreated(function () {
this.limit = new ReactiveVar(15);
this.autorun(() => {
this.subscribe('recent-topics', this.limit.get());
});
});
Make sure you add the grigio:babel package, and your Javascript file ends in .es6.js, .es6, or .jsx.
Explanation
In ES6 (aka ECMAScript 6), there's a new "fat arrow" syntax which is very similar to CoffeeScript's implementation. In ES6, when you do something like this:
someFunc = function () {
anotherThing((var1, var2) => {
this.thing = true;
});
};
It's the same as doing this:
someFunc = function () {
var self = this;
anotherThing(function (var1, var2) {
self.thing = true;
});
};
This is a scoping issue.
Inside of your Tracker.autorun, this no longer refers to the template, but the autorun's callback function. Inside of the autorun, try calling Template.instance().limit.get().
Better than using Template.instance().limit.get() (ryan's answer)
You should do something like this:
Template.home.onCreated(function () {
var self = this;
self.limit = new ReactiveVar(15);
self.autorun(function () {
self.subscribe('recent-topics', self.limit.get());
});
});

set THIS to current object inside array.prototype.reduce() [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 8 years ago.
I have a code which adds up a range of values. It takes two or three arguments and then create an array using those values and then add them up. My reduce object has a addup method which reduce its this.arr property using array.reduce() method. I have found that the THIS key indicates the global object inside reduce function. Why it indicates to global object inside reduce? How can I stick to the current object inside reduce using closure or something like that? I tried but couldn't find a way to figure this out.
There is nothing wrong with the code.It works fine.
addup method of reduce object:
addup:function(){
this.sum= this.arr.reduce(function(previous,current,index,array){
console.log(this);
return previous+current;
});
},
full code if required:
<html>
<body>
<script>
var reduce={
start:null,
end:null,
step:null,
args:null,
arr:[],
sum:null,
getrange:function(){
if(arguments.length==2){
this.args=arguments.length;
this.start=arguments[0];
this.end=arguments[1];
}
else if(arguments.length==3){
this.args=arguments.length;
this.start=arguments[0];
this.end=arguments[1];
this.step=arguments[3];
}
},
setarr:function(){
if(this.args==2){
for(i=this.start;i<=this.end;i++){
this.arr.push(i);
}
}
else if(this.args==3){
for(i=this.start;i<=this.end;i+=this.step){
this.arr.push(i);
}
}
},
addup:function(){
this.sum= this.arr.reduce(function(previous,current,index,array){
console.log(this);
return previous+current;
});
},
show:function(){
console.log(this.sum);
},
cleanup:function(){
this.arr.splice(0,this.arr.length);
this.sum=null;
}
}
reduce.getrange(1,5);
reduce.setarr();
reduce.addup();
reduce.show();
</script>
</body>
</html>
You can use bind to change the context of a function.
Live Demo
function callback(previous,current,index,array){
console.log(this);
return previous+current;
}
[1,2,3,4,5].reduce(callback);
var myObject = {};
[1,2,3,4,5].reduce(callback.bind(myObject));
Just store a reference to this before performing this.arr.reduce() so that you can use it from inside the callback:
addup:function() {
var self = this;
this.sum= this.arr.reduce(function(previous,current,index,array){
console.log(self);
return previous + current;
});
},

Categories