I am trying to make a search bar to collect a list of products which the user will then be able to select an array of products and add it to an order.
So far the products can be searched, added to a "products" array via an "add" button and they are able to see the data within products. They are also able to remove products that they do not want.
My issue is that I am trying to send the data from the "products" array with a parent form. The search component is located within the form as well as the list. But I do not know how I would send the array with the form.
I do not need to send the entire product object, but just the ID which will be used to link up the products with the order.
Here is where the component is:
<div class="uk-margin" id="search">
<label for="Search" class="uk-form-label">Search products to add</label>
<search input="ess"></search>
</div>
Here is the vuejs component data:
export default {
data() {
return {
keywords: null,
results: [],
products: []
};
},
watch: {
keywords (after, before) {
this.fetch();
}
},
methods: {
fetch() {
axios.get('/search', { params: { keywords: this.keywords } })
.then(response => this.results = response.data)
.catch(error => {});
},
addProduct (product) {
let duplicate = false;
this.products.forEach((item, index) => {
if (item.ID === product.ID) {
duplicate = true;
}
});
if (!duplicate) {
this.products.push(product);
}
},
removeProduct (product) {
Vue.delete(this.products, product);
}
}
}
Everything works fine, but my question is.. How am I able to pass the data back to the html / laravel to use it while sending data to the controller. I only need to send the "products" array, I have tried using input with the data but it isn't working. Does anyone know how I could do it, or is the best way to do so, using JavaScript and add them to an array by finding all the elements which are being displayed?
Many thanks.
Related
I am using react-native-searchable-dropdown for my react native project.
When onTextChange is fired I make a call to my backend with the text the user inputs.
Then I set the data I get back (array of objects) in the state:
async inputBrandText (text) {
const brands = await SearchForBrands(params);
this.setState((state) => {
return state.brands = brands
})
};
In the items element I reference this state array:
<SearchableDropdown
textInputProps={
{
placeholder: "",
underlineColorAndroid: "transparent",
style: {
...
},
onTextChange: text => this.inputBrandText(text)
}
}
items={this.state.brands}
/>
But the items get refreshed one key stroke after it should actually be refreshed.
So I think when the onTextChange event is fired, the items object or array is read in.
Then I change the this.state.brands object with the data from the backend.
But then no update occurs and the items object is not updated. Therefor the old items object is shown.
How can I solve this problem in a class based component?
Thanks!
PS: This is my ComponendDidMount:
async componentDidMount () {
const brands = await SearchForBrands(params);
this.setState((state) => {
return state.showBrandSuggestions = brands
})
}
Try this way
Your componentDidMount method should be like
async componentDidMount () {
const brands = await SearchForBrands(params);
this.setState({ showBrandSuggestions: brands });
}
Your inputBrandText method should be like
async inputBrandText (text) {
const brands = await SearchForBrands(params);
this.setState({ brands: brands });
};
I am passing multiple objects from laravel to vue and want to populate my vue objects with values given from the database.
The data from laravel:
Vue objects:
storeName: {},
storeUrl: {},
appName: {},
price: {},
share: {},
Where the data comes:
mounted() {
axios.get('/dashboard/affiliates')
.then(res => {
let data = res.data;
this.storeName = data.affiliates.shop_name;
console.log(data.affiliates);
})
As I understand, one of the bests ways would be to populate my vue objects it would be with filter function of javascript, but quite don't get it fully and don't know how to do it.
How could I populate vue objects with data that later on I could list them to the view in a v-for?
First use a compute function to link view and when you change storeName the app detect changes and paint again
Second, to make a array of shop_name use .filter to filter and them a .map to adapt your data
My advice is you store all data on vue data side, and on your computed method filter data and optional parse data, Also you can access to data with template, so you can parse data on template.
Something like this
export default {
name: 'loquesea',
data: {
affiliates: []
},
mounted() {
axios.get('/dashboard/affiliates')
.then(res => {
let data = res.data;
this.affiliates = data.affiliates;
})
},
computed: {
getStoresName() {
return this.affiliates.filter(() => {
// what you want
return true;
}).map((affiliate) => {
return affiliate.shop_name;
})
}
}
}
on your template.html
<ul id="example-1">
<li v-for="storeName in getStoresName">
{{ storeName }}
</li>
</ul>
I'm new to vue, but I carefully read the docs for vue and vuex as well. But I'm stuck with the following issue. I also do think it's neither that I would not get it done somehow, but I'd like to go for a clean and probaply best practive approach.
The Setup:
- I have some entities
- I have some users
- lets say an entity can belong to multiple users
Now what I want to accomplish is to display a list of all users having those checked which are assigned to the entity.
I have the following vuex store:
export default new Vuex.Store({
state: {
users: [],
entities: []
},
getters: {
USERS: state => state.users,
ENTITIES: state => state.entities,
ENTITY: state => id => {
return state.entities.find(entity => entity.id == id)
}
},
mutations: {
SET_USERS: (state, payload) => {
state.users = payload
},
SET_ENTITIES: (state, payload) => {
state.entities = payload
},
UPDATE_DEVICE: (state, payload) => {
state.entities = state.entities.map(entity => {
if(entity.id === payload.id){
return Object.assign({}, entity, payload.data)
}
return entity
})
}
},
actions: {
GET_USERS: async (context) => {
let { data } = await Axios.get('/api/v1/users')
context.commit('SET_USERS', data)
},
GET_ENTITIES: async (context) => {
let { data } = await Axios.get('/api/v1/entities')
context.commit('SET_ENTITIES', data)
},
UPDATE_ENTITY: ({commit}, payload) => {
Axios.put('/api/v1/entities/' + payload.id + '/', payload.data).then((response) => {
commit('UPDATE_ENTITY', payload)
});
}
}
})
My Entity-Component loads the users from the store within the created hook. The the entity's data is get from the store from the computed property entity(). Also the list of all users is served by a computed property users().
created(){
if(!this.$store.getters.USERS.length) this.$store.dispatch('GET_USERS')
},
computed: {
entity(){
const entityId = this.$route.params.id
return this.$store.getters.ENTITY(entityId)
},
users(){
return this.$store.getters.USERS
}
}
Then within the template I show all the users and a checkbox:
<ul>
<li v-for="(user, i) in users" :key="i">
<input type="checkbox" :value="user" :id="'user_'+i" :name="'user_'+i" v-model="???" />
<label :for="'user_'+i">{{user.name}}</label>
</li>
</ul>
I also have a second list of all users which belong to the entity within the the same component's template like the following which I'd like to keep in sync with the 'selectable list'. So all users with a checked checkbox should be listed in that list:
<ul>
<li v-for="user in entity.users" :key="user.id">
{{user.name}}
</li>
</ul>
And here is where I'm stuck at:
should I use a computed property for the device.users with get() and set() and use this as v-model on the checkboxes? I tried that but it hasn't worked because the user object of the all-users list and the objects of the device.users list were not the same objects even if they represent the same user. And at that point I think I'm doing the whole thing way to complex and I'm simply overlooking the common way practiced vue-users would do it.
So long story short: what is the best way to solve this task?
I think it's a mostly common task.
Thanks for every answer, if more code / details required I of cause will provide them!
How does the structure of entity look? Assuming they have an array 'users', you could calculate the value for the checkbox by providing a basic javascript function that checks if that user's unique ID is in the list for this entity.
In computed make a new property (so you don't recalculate the same array for every element in v-for):
userIdsWithEntity() {
if (!this.entity) return []; // necessary in case entity hasn't been instantiated yet
return this.entity.users.map(x => x.id)
}
Then provide a simple function to the checkbox value that returns true or false: :value="userIdsWithEntity.includes(user.id)"
Instead of v-model (which is :value and #input/#change to update the property provided in :value rolled into one directive, so you might get conflicts with your :value definition), use #change to handle the (un)checking of the checkbox, dispatching an action to vuex to remove/add that user to the entity.
In my CMS system, I can add pages. I want to also edit the existing content of these pages.
What I am trying to achieve is:
User edits page
Page updates in same firebase document where it was created
Page displays new content
Right now, I have set up getter and setter in computed where getter is getting data from the firebase collection and is providing the corresponding text I want to edit, and setter will commit to the changes I do with this text.
data: () => ({
title: null,
content: null
}),
computed: {
pages: {
get() {
return this.pageIndex
},
set() {
this.title
this.content
}
}
},
To update the document in firebase I am triggering this method:
methods: {
async update(id) {
return db
.collection('PAGES')
.doc(id)
.set({
title: this.title,
content: this.content
})
.then(() => {
return this.fetchPage()
})
},
}
But it posts this in my firebase document:
title: null
content: null
In the console, it shows undefined. When posting the data as with array or objects, it does post whatever changes I made. But that is my problem, I do not want to post it as an object or array, I am trying to post it as field names inside a document.
The current way I am doing it results in this:
What can I change to post the updated title and content?
Edit:
If I do it this way it will post the data but it will post as an object and an array:
data: function() {
return {
updatedPayload: {
title: null,
content: null
}
}
},
computed: {
pages: {
get() {
return this.pageIndex
},
set() {
this.updatedPayload = { title: this.title, content: this.content }
}
}
},
methods: {
async update(id) {
// return db.doc(`pages/${page.id}`)
const self = this
const pages = self.pages
return db
.collection('PAGES')
.doc(id)
.set({ pages })
.then(() => {
return this.fetchPage()
})
}
}
Here is the HTML
<tbody v-for="(page, idx) in pages" :key="page" class="">
<b-input v-model="page.title"></b-input>
<VueEditor v-model="page.content"></VueEditor>
</tbody>
So the dilemma is, I can only update data with an object, but I can not update data with field name, as it appears.
The OP of this thread is trying to achieve the same outcome as me, populate data for an input field, where as input shows existing information, and can populate new data. In my case, I need 2 inputs to populate new data, it already displays existing data from firebase.
This is probably easy for someone, but I just can't get it. So I have a list of items to display:
My service that fetches the data, configService.ts
ngOnInit() {
getConfig(): Observable<any> {
return this.http.get<any>('/api/config').map(res => res);
}
}
My savedSearhes component that populates data in the ngFor:
this.configService.getConfig().subscribe(data => {
this.userSavedSearches = data.isr.me.savedSearches //get an array of items
});
the html to display data:
<div *ngFor="let savedsearch of userSavedSearches">
{{savedsearch.name }}
</div>
The main issue I have, is I have another component that I use to add a new item to the same server.
saveSearch() {
this.saveSearchObject = {
name: this.SearchName,
description: this.SearchDescription,
context: this.theContext,
}
this.searchService.createSavedSearch(this.saveSearchObject).subscribe(data => {
console.log(data) // newly added item to server
})
}
The service that posting new item to server:
createSavedSearch(search: SavedSearch): Observable<SavedSearch> {
return this.http.post<SavedSearch>('/api/searches/', search)
}
When I add a new item, the item actually gets added to the server. But I don't see the "savedSearches" component display added item, only when I reload the page I can see new item added.
How to add new item to the server and see its being added with new item in other component without reloading the page.
You can achieve it by Creating a subject where saveSearch function lies
let subjectUserSavedSearches = new Subject();
let obsrvUserSavedSearches = subjectUserSavedSearches.AsObservable();
saveSearch() {
this.saveSearchObject = {
name: this.SearchName,
description: this.SearchDescription,
context: this.theContext,
}
this.searchService.createSavedSearch(this.saveSearchObject).subscribe(data => {
this.userSavedSearches = data;
this.subjectUserSavedSearches.next(this.userSavedSearches);
})
}
Now watch that obsrvUserSavedSearches on the component you need to show data.
The best way is to move methods getConfig() and saveSearch() in a service and just create a subject for userSavedSearches and an Observable to watch the same.
You won't see it unless you do a getConfig() again. Use a .switchMap() to chain your http calls.
saveSearch() {
this.saveSearchObject = {
name: this.SearchName,
description: this.SearchDescription,
context: this.theContext,
}
this.searchService.createSavedSearch(this.saveSearchObject)
.switchMap(data => {
console.log(data) // newly added item to server
return this.configService.getConfig();
})
.subscribe(data => {
this.userSavedSearches = data.isr.me.savedSearches //get an array of items
})
}
Otherwise, unless your savedSearches() actually returned a newly refreshed list, you can do it in your subscribe:
saveSearch() {
this.saveSearchObject = {
name: this.SearchName,
description: this.SearchDescription,
context: this.theContext,
}
this.searchService.createSavedSearch(this.saveSearchObject).subscribe(data => {
this.userSavedSearches = data
})
}