I dont get the following function translated to ecmascript 2015
route: {
data: function () {
return this.$http.get('/api/posts?sort=title&order=1').then(
posts=>{this.table.posts = posts.data}
);
}
},
because this isnt refering to the window object I get the
[vue-router] Uncaught error during transition: be.js:3660:7
TypeError: undefined has no properties[Learn More]be.js:16572:13
You can use certain features such as shorthand method names and slightly more compact arrow functions to make it looks more ES2015, but it won't change the functionality:
route: {
data() {
return this.$http
.get('/api/posts?sort=title&order=1')
.then(posts => { this.table.posts = posts.data });
}
},
You couldn't replace the data hook function with an arrow functions, because this would refer to the wrong context (either to window or undefined), as its this would be defined by its surrounding lexical scope and could not be overriden.
Related
I'm building an app to consume a json and list it with a search filter input and other stuff.
I've already tried to create the function but it didn't work.
Codesandbox URL
https://codesandbox.io/s/vue-template-7iev3?fontsize=14
search: "",
Its showing "TypeError: Cannot read property 'search' of undefined" but its defined
TypeError: Cannot read property 'search' of undefined" doesn't mean that "search" is undefined but the parent object is. In your case, "this.search", this is undefined in your callback. You should use "self.search" because you already defined it or just change your syntax into:
computed: {
produtoFiltrado: function() {
return this.produtos.filter((cust) => {
return cust.nome.match(this.search);
});
}
}
Arrow functions doens't bind their "this" to their context so you can access your vue methods, props, data etc. using this without any problems
To avoid "TypeError: Cannot read property 'includes' of null" problem, better to add line before return
computed: {
filteredItems() {
return this.customers.filter(item => {
return (item.title || '').toLowerCase().indexOf((this.search || '').toLowerCase()) > -1
})
}}
(this.search || '') will do trick..
I can't seem to find a way to convert the JSON's value into a function reference. Need help?
I have attached herewith a small code snippet for reference
//addButton.json
"row": [
{
"type": "button",
"name": "Add",
"label": "add",
"color": "warning",
"size": "lg",
"colsize": "3",
"onButtonClick": "this.handleAddRequest"
}
]
// CustomForm.jsx
import addBankApiInfoPage from '../addBankApiInfo.json';
class CustomForm extends React.Component{
handlerFunction = ()=>{
this.map.rowData(row=>{
if (rowData[row].startsWith("this.")) {
rowData[row] = eval("this" + r[k].substring(4, r[k].length));
}
});
}
Running this code throws error as
Uncaught TypeError: Cannot read property 'handleAddRequest' of undefined
at eval (eval at <anonymous> (Add.jsx:57), <anonymous>:1:6)
at Add.jsx:57
at Array.map (<anonymous>)
at Add.jsx:48
at Array.map (<anonymous>)
at Add.jsx:45
at Array.map (<anonymous>)
at new Add (Add.jsx:3
1) Arrow functions do not bind the this
Your problem is almost certainly in that arrow functions do not bind the containing object to this.
class Good {
meth(){return this}
}
class Good {
meth: function self(){return this}
}
class Bad {
meth: ()=>{return this} //will be undefined
}
2) There is no point in doing eval.
There's no need to do eval("this" + r[k].substring(4, r[k].length))
eval should be avoided whenever possible
you already have "this" as part of the string
If .substring (or .slice) with no second argument goes to the ends of the string
In many production environments eval will not even be available, since it is a very common cause for security vulnerability, and also has poor performance and tooling.
In your case, if you want a reference to the running code's this, you can do
if (rowData[row].startsWith("this.")) {
rowData[row] = this[r[k].substring(4)]
}
If you want a method bound to the this target, that you can then call from anywhere, and not just the function in that parameter, you can bind it one of these two ways:
if (rowData[row].startsWith("this.")) {
rowData[row] = this[r[k].substring(4)].bind(this)
}
// OR
if (rowData[row].startsWith("this.")) {
rowData[row] = () => this[r[k].substring(4)] // the `handlerFunction`'s `this` is captured by the closure
}
PS: even .bind can't put this in an arrow function.
console.log((()=>this).bind(1)())
VM3283:1 Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
console.log((function(){return this}).bind(1)())
VM3362:1 Number {1}
I want to pass an Laravel object to my Vue component. In Vue I want to parse the data to an JSON object and I already tried this solution.
In my blade I have this:
<creator :object="parseData({{ $object->toJson() }})"></creator>
And in my component I have this:
data() {
return {
object: null
}
},
methods: {
parseData(data) {
this.object= JSON.parse(data);
}
}
I also tried
props: ['object']
instead of data()
This gives me the following error:
[Vue warn]: Property or method "parseData" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
Can you tell me what I am doing wrong?
SOLVED
I tried it again today and for some reason it worked. Thanks for your time guys!
Your parseData method needs to be defined within the methods section of your JS.
Try:
data() {
return {
ball: null
}
},
methods: {
parseData(data) {
this.object= JSON.parse(data);
}
}
Edit: and do what #Piotr said :)
First: You didn't add property object to your component. To fix this you have to add this line
props: ['object'],
just before your data function.
Second: you have to define parseData function in methods part of your component. Fix it as follows:
methods: {
parseData () {
//your function logic
}
}
Vue needs to define methods, watchers, computed properties within proper section.
Now your code is compete.
I have done a service that gets a json file from the server with the translated values of the labels of my webapp. Seems to work fine:
mobilityApp.service('serveiTraduccions', function($resource) {
this.getTranslation = function($scope) {
var languageFilePath = 'traduccions/traduccio_en.json';
$resource(languageFilePath).get(function (data) {
$scope.translation = data;
});
};
});
What I am trying to do is acces that "$scope.translation" from my controler, I tried all and nothing worked. The object is saved in my $scope as you can see:
how can I get the values of the "registroBtnRegistro", "registroErrorRegistro" etc ?
Thanks in advance !
I tried:
console.log($scope.translation); -> undefined
console.log($scope['translation']); -> undefined
console.log($scope.translation.registroBtnRegistro); -> TypeError:
Cannot read property 'registroBtnRegistro' of undefined
console.log($scope.translation['registroBtnRegistro']); -> TypeError:
Cannot read property 'registroBtnRegistro' of undefined
Maybe you're trying to access these values from another $scope that not inherits the scope where you've created your translation model.
Try to assign this model directly to $rootScope, so you can access it from every scope:
mobilityApp.service('serveiTraduccions', function($resource, $rootScope) {
this.getTranslation = function() {
var languageFilePath = 'traduccions/traduccio_en.json';
$resource(languageFilePath).get(function (data) {
$rootScope.translation = data;
});
};
});
this answer is a blind attempt because your original post lacks basic information like the call from the controller.
we can refine it until we make it work.
First, you should be returning something from your method:
mobilityApp.service('serveiTraduccions', function($resource) {
this.getTranslation = function() {
var languageFilePath = 'traduccions/traduccio_en.json';
return $resource(languageFilePath);
};
});
You are using $resource but you might as well use basic $http.get(). at least it doesn't look like a restful api to me.
In any case, because it's an asynchronous request, it will not return the list of translated strings, but a resource "class" that allows methods like get, delete or the more general query():
from the docs: default methods are
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
sidenote: injecting $scope in a service doesn't make much sense to me: services are used to encapsulate common logic accross components. However, you can pass a scope instance as a parameter.
Then, the controller that uses this should have the service injected and use a callback to get the results when they have arrived (asynchronous operation!):
TraduccioCtrl ... {
$scope.translation = {}; // avoid undefined when the view just loads
ServeiTraduccions.getTranslation.query(function (response) {
$scope.translation = response; // and angular's two-way data binding will probably do the rest
});
}
The Angular docs about ng-resource have a working example. Other questions in SO have addressed this already too, like Using AngularJS $resource to get data
I am needing the scope of $scope.press to fall within the scope of ReleaseCtrl, wondering the best way to refactor the syntax to do so... I know it's a scope inheritance issue because when I try to post the same console.log($scope.press) below the close of the query function, I get an undefined response as opposed to the array, which properly shows up within the bounds of the "Release" query function.
app.service('Releases', function ($resource) {
return $resource('http://127.0.0.1:3000/json', {}, {
'query': {method: 'GET', isArray: true}
});
});
app.controller("ReleaseCtrl", function (Releases, $scope){
Releases.query(function(data, $scope){
$scope.press = data;
console.log($scope.press);
for(var i=0;i<$scope.press.length;i++) {
console.log($scope.press[i].name)
}
});
$scope.loadRelease = function() {
console.log("Loading Press Release");
}
})
I imagined the Releases.query function could find its way to replace the function directly above it, but, Releases of course is undefined at that point because it has not yet been passed / injected.
I think this is fairly simple to fix, but I do not know exactly the best way to go about it.
Best regards,
Sean
Here is what I ended up doing:
app.service('Releases', function ($resource) {
return $resource('http://127.0.0.1:3000/json', {}, {
'query': {method: 'GET', isArray: true}
});
});
app.factory ('release', function (Releases){
return Releases.query();
})
app.controller("ReleaseCtrl", function (release, $scope){
$scope.press = release;
console.log($scope.press);
$scope.loadRelease = function() {
console.log("Loading Press Release");
}
})
After looking around, I believed injecting with service was better practice than what I was doing earlier, so I just refactored it that way. I think re-writing what is in the service within the factory is even better. Will update when I get there.
A thing to note: Whatever you query must have more than one result. Otherwise it comes back as an object, not an array, and it does not work correctly. Maybe somebody can explain why?
Since you are passing $scope as a parameter to the function you pass to .query, and because .query does not call the callback with any arguments, $scope is probably undefined.
You need to use the following syntax for accessing your resources:
var data = Releases.query(function () {
$scope.press = data;
// ... Further operations with data.
});
See usage note in the docs