I know that we can re-initialize the data like this:
function initialData() {
return {
is_active: true,
is_collapsed: true,
resetable_data: 'value',
resetable_stat: 4
}
}
export default {
...
data() {
return {
initialData()
}
},
...
But I am wondering how we can re-initialize only a portion of the data. I mean something like:
function initialData() {
return {
resetable_data: 'value',
resetable_stat: 4
}
}
export default {
...
data() {
return {
is_active: true,
is_collapsed: true,
initialData()
}
},
...
Is there a way to do this?
Try Object.assign():
function initialData() {
return {
resetable_data: 'value',
resetable_stat: 4
}
}
export default {
...
data() {
return Object.assign(
{
is_active: true,
is_collapsed: true,
},
initialData()
);
},
...
Object.assign(target, ...sources) copies the properties of the ...sources (in this case, the object returned by initialData()) into the target (in this case the object with is_active and is_collapsed), returning the target object.
Related
I am building a datatable with multi-column sorting functionality. As up to now, the sorting functionality is working fine, what I am unable to get is, right parameters into the url. As I am only passing $sorts to the component, as a prop, hence I'm using this.$inertia.get to pass the $sorts back to the controller, which is returning back the sorted data. But due to passing sorts: this.sorts within the Inertia get method, its returning back the url query as http://127.0.0.1:8000/users?sorts[name]=asc. How can I get the required parameter within the Inertia get method so I get a url query as suchhttp://127.0.0.1:8000/users?sort_field=name&sort_direction=asc as well as pass the $sorts as well so it returns back the expected data.
Controller
public $sorts = [];
public function initalizeSortingRequest()
{
$this->sorts = request()->get('sorts', $this->sorts);
}
public function applySorting($query)
{
foreach ($this->sorts as $sort_field => $sort_direction) {
$query->orderBy($sort_field, $sort_direction);
}
return $query;
}
Component
<script >
methods: {
sortBy(field) {
if (!this.sorts[field]) {
this.sorts[field] = 'asc';
} else if (this.sorts[field] == 'asc') {
this.sorts[field] = 'desc';
} else {
delete this.sorts[field];
}
let route = this.route('users.index', {
sorts: this.sorts
})
this.$inertia.get(route, {}, {
only: ['usersData'],
preserveState: true,
preserveScroll: true
})
}
}
</script>
I recently made a screencast on building a datatable with InertiaJS and Laravel.
The gist of it is:
import AppLayout from '#/Layouts/AppLayout';
import Pagination from '../Jetstream/Pagination';
import { pickBy, throttle } from 'lodash';
export default {
components: {
AppLayout,
Pagination,
},
props: {
users: Object,
filters: Object,
},
data() {
return {
params: {
search: this.filters.search,
field: this.filters.field,
direction: this.filters.direction,
},
};
},
methods: {
sort(field) {
this.params.field = field;
this.params.direction = this.params.direction === 'asc' ? 'desc' : 'asc';
},
},
watch: {
params: {
handler: throttle(function () {
let params = pickBy(this.params);
this.$inertia.get(this.route('users'), params, { replace: true, preserveState: true });
}, 150),
deep: true,
},
},
};
Then in the controller index action:
public function index()
{
request()->validate([
'direction' => ['in:asc,desc'],
'field' => ['in:name,city']
]);
$query = User::query();
if (request('search')) {
$query->where('name', 'LIKE', '%'.request('search').'%');
}
if (request()->has(['field', 'direction'])) {
$query->orderBy(request('field'), request('direction'));
}
return Inertia::render('Users', [
'users' => $query->paginate()->withQueryString(),
'filters' => request()->all(['search', 'field', 'direction'])
]);
}
You can watch the screencast here.
I've been looking for quite a while but being a novice I can't find an answer.
I would like to filter my array with the id of a property I think is the wrong syntax.
Thanks for your help
components
export default {
props: ["user", "recette"],
data() {
return { email: this.$route.params.email };
},
components: {},
methods: {},
computed: {
filteredItems: function () {
return this.recette.filter((recettes) => {
return recettes.cat_recetteId === 1;
});
},
},
};
VIEW
<template>
<div>
<myrecette :recette="recette"/>
<myfooter />
</div>
</template>
<script>
import myrecette from "../components/recette";
import myfooter from "../components/myfooter";
export default {
name: "",
data() {
return {
recette: "",
user: "",
};
},
components: {
myrecette,
myfooter,
},
created: function() {
this.axios.get("http://localhost:3000/recette/all_recette/").then((res) => {
(this.recette = res.data.recette),
this.axios
.get(
"http://localhost:3000/user/rec_user/" + this.$route.params.email
)
.then((res) => {
this.user = res.data.user;
});
});
},
};
</script>
<style scoped></style>
NODE
router.get("/all_recette", (req, res) => {
db.recette
.findAll({
include: { all: true },
})
.then((recette) => {
if (recette) {
res.status(200).json({
recette: recette,
});
} else {
res.json("il n'y a pas de recettes");
}
})
.catch(err => {
res.json(err);
});
});
Here is my complete code as well as my node route.
My error return is
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in render: "TypeError: this.recette.filter is not a function"
The filter works by keeping items which return true, so if you want all items having a cat_recetteId of 1, you would change it to:
computed: {
filteredItems: function() {
if (!this.recette) return [];
return this.recette.filter((recettes) => {
return recettes.cat_recetteId === 1;
});
},
},
It's also good practice to use an arrow function in most cases inside of a computed.
Your filter callback function should return true or false. You're 1) not returning anything and 2) assigning a value (=) instead of doing a comparison (==/===).
computed: {
filteredItems: function() {
return this.recette.filter(function(recettes) {
return recettes.cat_recetteId === 1;
});
},
},
I pass a query to apollo client in my script tag, in my template file but I don't want to do it every time. Rather, I'd like to pass a boolean in a prop and then run the query (or not) based on the boolean.
<template>
...
</template>
<script>
import {
MY_QUERY
} from 'util/queries';
props: {
productId: {
type: String,
default: '',
},
suppressGraphQlQuery: {
type: boolean,
default: false,
}
},
data() {
return {
relatedProducts: [],
loading: 0,
preloading: true,
};
},
apollo: {
relatedProducts: {
query: MY_QUERY,
variables() {
return {
id: this.productId,
};
},
},
},
</script>
I want to be able to utilize suppressGraphQlQuery prop not to call the apollo client, but not sure how to do it. Is it possible to not to run the query when my prop === true?
Thank you in advance.
You can skip a query like this:
export default {
props: {
skipQuery: {
type: Boolean,
default: false,
},
},
apollo: {
relatedProducts: {
query: MY_QUERY,
variables() {
return {
id: this.productId,
};
},
skip() {
return this.skipQuery;
},
},
},
};
my props is like this
house = {
kitchen:{
sink: ''
}
}
I tried something like this, didnt work.
props: {
house: {
type: Object,
default: () => {
kitchen : {
sink: ''
}
}
}
},
How to set default props for such object?
From the docs:
Object or array defaults must be returned from a factory function
So the problem is that you are not returning the default object.So you can either do:
props: {
house: {
type: Object,
default: () => ({ // <= note the parenthesis
kitchen : {
sink: ''
}
}) // <= here also
}
},
Or
props: {
house: {
type: Object,
default: () => {
return {
kitchen : { // <= note the return
sink: ''
}
}
}
}
},
The following solution should work :
props: {
house: {
type: Object,
default: () => ({
kitchen: {
sink:''
}
})
},
}
check this codesandbox
if the above solution doesn't work, you could use a normalized computed property :
props: {
house: { type: Object }
},
computed: {
normalizedHouse() {
return {
kitchen:{
sink: ''
}
}
}
}
I get syntax error when combining Vuex localcomputed object with get/set together with store mappings.
As seen in the Vuex docs you can map your store methods like this with the object spread operater like:
computed: {
localComputed () { /* ... */ },
// mix this into the outer object with the object spread operator
...mapState({
// ...
})
}
https://vuex.vuejs.org/en/state.html##object-spread-operator
Also you can create computed setters like:
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
https://v2.vuejs.org/v2/guide/computed.html#Computed-Setter
I can create either a computed object with get set or have mapState/mapGetters etc. - but not in combination. It break the syntax (error is: expected function name after the function declarations).
computed: {
localComputed () {
localMethod: {
get: function () {
// retrieve
},
set: function (newContent) {
// set
}
}
}, ...mapState([
]), ...mapGetters([])
}
How do i combine these two?
You are trying to define localMethod inside localComputed.
In the docs, localComputed is just an example name for a computed property in your component. You don't have to put all of your other local computed properties within it.
Therefore, you should be able to do the following:
computed: {
localComputed: {
get: function () {
// retrieve
},
set: function (newContent) {
// set
}
},
anotherLocalComputed: {
get: function () {
// retrieve
},
set: function (newContent) {
// set
}
},
...mapState([]),
...mapGetters([])
}
Here is the working sample. I have been using this approach for more than a year
// in some utils/vuex.js file
export const mapSetter = (state, setters = {}) => (
Object.keys(state).reduce((acc, stateName) => {
acc[stateName] = {
get: state[stateName],
};
// check if setter exists
if (setters[stateName]) {
acc[stateName].set = setters[stateName];
}
return acc;
}, {})
);
In your component.vue file
import { mapSetter } from 'path/to/utils/vuex.js';
...
export default {
name: 'ComponentName',
computed: {
...mapSetter(
mapState({
result: ({ ITEMS }) => ITEMS.result,
total: ({ ITEMS }) => ITEMS.total,
current: ({ ITEMS }) => ITEMS.page,
limit: ({ ITEMS }) => ITEMS.limit,
}),
{
limit(payload) {
this.$store.dispatch({ type: TYPES.SET_LIMIT, payload });
},
},
)
},
}
now v-model binding should work.