How to display user name instead of id (foreign key) in laravel & vue.js - vue.js

I want to display the user name instead supervisor_id in the table list in Vue.js. this is one to many relationship. supervisor_id is foreign key from user table.
/// this is view in vue.js. I want to to change work.supervisor_id into something like work.user.name, but it do not work.
<tr v-for="(work,index) in works.data" :key="work.work_id">
<td>{{index+1}}</td>
<td>{{work.work_name}}</td>
<td>{{work.supervisor_id}}</td>
<td>{{work.payment}}</td>
<td>{{work.created_at | myDate}}</td>
<td>{{work.end_date}}</td>
<td>{{work.worker_id}}</td>
<td>
/// this is my script in vue.js
<script>
export default {
data() {
return{
editmode: false,
works:{},
index:1,
users:{},
form: new Form({
work_id:'',
work_name:'',
description:'',
payment:'',
location:'',
end_date:'',
worker_id:'',
application_status:'New',
supervisor_id:'',
})
}
},
methods:{
getResults(page = 1) {
axios.get('api/work?page=' + page)
.then(response => {
this.works = response.data;
});
},
loadWork(){
if(this.$gate.isClerk()){
// axios.get('api/work').then(({data})=>(this.works = data));
axios.get('api/work').then(response => (this.works = response.data));
}
},
/// this is my work controller
public function index()
{
return Work::latest()->paginate(10);
}
the data in the vue.js devtool

For this to work, it would require the a relationship on the Work model which returns the supervisor record which you require.
This will allow you to get the supervisor's (or user's depending on the relationship) name.
Work Model (app\Work.php):
public function supervisor()
{
return $this->hasOne(User::class, 'supervisor_id');
}
Now in your controller, you can use the ->with() eloquent method to eager load a relation:
public function index()
{
return Work::with('supervisor')->latest()->paginate(10);
}
You should now be able to access the supervisor name within vue using:
{{ work.supervisor.name }}
I hope this helps.

Related

Calling function in VueApollo after API response

I am using Vue and Apollo and I am making a querie that looks just like the box below.
After I get the API response, I would like to call a method from my methods object. However Vue, doesn't give me acess to it within apollo object.
I would like to know how can I call one of my methods, but only after I am sure I got that response, without having to manually trigger it with a button or something else.
apollo: {
materials: {
query: gql`
query allMaterials($tenantId: ID, $name: String) {
tenantMaterials(tenantId: $tenantId, name: $name) {
edges {
node {
name
materialType {
name
id
}
brand
vendor
size
unit
inventory
createdAt
updatedAt
isActive
updatedBy
id
}
}
totalCount
}
}
`,
variables() {
return {
name: null
};
},
fetchPolicy: "cache-and-network",
update: response => {
return response.tenantMaterials.edges;
//I want to call a function/method after this response
},
skip: false
},
}
Use update(data) or result(result, key)
update(data) {return ...} to customize the value that is set in the
vue property, for example if the field names don't match.
result(ApolloQueryResult, key) is a hook called when a result is
received (see documentation for ApolloQueryResult (opens new window)).
key is the query key in the apollo option.
https://apollo.vuejs.org/api/smart-query.html

Vue.js reactivity of complex objects in a store

My Problem
I am trying to store a list of complex items in a store and access these items from a component. I have a mqtt interface which receives data for these items and updates their values in the store. However, the ui does not react to updating the properties of these items.
Structure
In my store, i have two mutations:
state: {
itemList:{}
},
mutations: {
/// adds a new item to itemList
[ADD_ITEM](state, item) {
if (item&& !state.itemList[item.itemId])
{
Vue.set(state.itemList, item.itemId, item);
}
},
/// updates an existing item with data from payload
[SET_ITEM_STAT](state, { itemId, payload }) {
var item= state.itemList[itemId];
if (item) {
item.prop1 = payload.prop1;
item.prop2 = payload.prop2;
}
}
},
actions: {
/// is called from outside once when connection to mqtt (re-)established
initializeMqttSubscriptions({ commit, dispatch }, mqtt){
mqtt.subscribeItem("items/stat", async function(itemId, topic, payload) {
commit(SET_ITEM_STAT, { itemId, payload });
});
},
...
}
I also tried:
setting the item properties using Vue.set(state.itemList, itemId, item);
setting the item properties using Vue.set(state.itemList[itemId], 'prop1', payload.prop1);
I also want to show how i built the Component which accesses and displays these items (Item.vue). It is one component, that gets passed the itemId to show via the route params. I've got the following computed properties:
<template>
<div class="grid-page">
<h1 class="page-title">Item- <span class="fw-semi-bold">{{ id }}</span></h1>
<div>
<Widget v-if="item">
{{ item.prop1 }}
...
...
computed: {
id(){
return this.$route.params.itemId;
},
item(){
return this.$store.state.items.itemList[this.id];
}
}
So when the route parameter itemIdchanges, i successfully can see the item data, everything is fine. But if i update the properties of an item with the mutation shown above, no update in view is triggered.
I would be very happy if someone could give me a hint what i am doing wrong here. Thanks in advance!
Since i can't comment to ask for some clarifications,
If you're itemlist is an nested object, try out with Object.assign
[SET_ITEM_STAT](state, { itemId, payload }) {
var item= state.itemList[itemId];
if (item) {
this.state.itemList[itemId] = Object.assign({}, this.state.itemList[itemId].prop1, {payload.prop1})
this.state.itemList[itemId] = Object.assign({}, this.state.itemList[itemId].prop2, {payload.prop2})
// or
this.state.itemList[itemId] = Object.assign({}, this.state.itemList[itemId], {prop1: payload.prop1, prop2: payload.prop2})
}
}
Let me know how it goes
https://v2.vuejs.org/v2/guide/reactivity.html#For-Objects

How to add tenant / organization id to every URL and read it inside controller

I am writing an ASP.NET Core web application. In my application, the user can be a member of one or more organizations (this information is stored in the DB). I would like to give the users the possibility to select the context of organization in which the whole app should be running. This context should be passed to every controller so that I can do proper checks and return only the data from the selected org.
In other words, I would like to achieve the state when the user can access the app via:
app.mydomain.com/org1/controller/action/id and using a dropdown they should be able to switch to org2 and access app.mydomain/org2/controller/action/id
In both cases I need to be able to read the organization inside the controller. This should apply to every controller.
How should this be done? Is it possible to construct a route that would handle it and just add new parameter to every controller, e.g. orgId? Or maybe there should be a service that reads this information from the URL and can be injected into controllers? How would the route look then? I have read some tutorials about handling multiple languages in a similar way (with the culture in URL) but I am not able to translate that into my case.
For how to pass the select org id to the controller:
View:
<form action="/Orgnization/Test">
<select id="select" name="select" asp-items="#ViewBag.Sel"></select>
</form>
#section Scripts
{
<script>
$(document).ready(function () {
$("#select").change(function () {
$('form').submit();
});
})
</script>
}
Configure selectlist:
public class HomeController : Controller
{
public IActionResult Index()
{
//for easy testing,I just set it manually...
ViewBag.Sel = new List<SelectListItem>() {
new SelectListItem() { Value = "-1", Text = "--- Select ---" },
new SelectListItem() { Value = "org1", Text = "org1" },
new SelectListItem() { Value = "org2", Text = "org2" },
new SelectListItem() { Value = "org3", Text = "org3" },
};
return View();
}
}
Controller:
public class OrgnizationController : Controller
{
public IActionResult Test(string select)
{
//the select is the value you choose
//do your stuff....
return View();
}
}
If you want to add prefix to the route and get it in the controller:
Startup.cs:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{orgid?}/{controller=Home}/{action=Privacy}/{id?}");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Privacy}/{id?}");
});
Controller:
public class OrgnizationController : Controller
{
public IActionResult Test(string select)
{
var org = "";
if (select==null)
{
var path = Request.Path.ToString();
org = path.Split('/')[1];
}
//do your stuff....
return View();
}
}
Result:

Redux - Filterable category with products - Actions & Filter

My state looks exactly like this:
{
categories: {
"unique-category-id" {
"data": {
// All kind of data (name, description ,etc )
"products": [
{
// Products that belong to this category with the current filter
}
]
},
"readyState": "CATEGORY_FETCHED",
"query": { // This object holds all the params that the filter allows to choose from
"brands": [],
"options": {
"usb": true
"minPrice": 200
}
}
}
}
}
This works and fetches data correctly. Now it's time to implement the filtering funcionality. I am trying to make it work like this, not sure if this is the "redux" way of doing things.
1.- On each filter on the category page we assign a click handler:
<li onClick={this.toggleFilterField} key={item.VALUE}>{item.NAME}</li>
toggleFilterField is passed into the container via mapDispatchToProps:
const mapDispatchToProps = (dispatch) => {
return {
toggleFilterField: (category, filter) => {
dispatch(toggleFilterField(category, filter))
}
}
}
export { CustomTagFilter };
export default connect(null, mapDispatchToProps)(CustomTagFilter);
2.- My toogleFilterField should just return an action like this one:
return {
type: CHANGE_FILTER,
category,
filter
}
Then my category_reducer.js should handle this action and update the following state key
state.categories[unique-category-id].query
Now this is OK, but now, after applying the filter to the state I would have to refetch the data from the category.
How and where do I fire a new action based on a previous action success?
Is this the correct way of handling filtered elements in redux that come from a paginated API?

how to pass value ember view to controller

I am new in pretty ember js development .
I have done view below code
{{view "select" content=model prompt="Please select a name" selectionBinding="" optionValuePath="content.body" optionLabelPath="content.title"}}
using following Json
posts = [{
title: "Raja",
body: "There are lots of à la carte software environments in this world."
}, {
title: "Broken Promises",
body: "James Coglan wrote a lengthy article about Promises in node.js."
}];
and Router
App.InRoute = Ember.Route.extend({
model: function () {
return posts;
}
});
My Requirement is passing that combo box selected value to controller
App.InController = Ember.Controller.extend({
alert("combobox selected item")
});
And how an i access that value apicontoller in .net mvc 4
public class ValuesController : ApiController
{
string value= combo box selected value
}
Your "select" view's value attribute needs to be bound to a property on the controller:
add the following to your view's attributes: value=selectedItem
In your controller:
Add "selectedItem"
App.InRoute = Ember.Route.extend({
selectedItem: null,
model: function () {
return posts;
}
});
Now your all set to send it to your Api end point. You could create an action handler and make it happen there. Here is a quick example:
App.InRoute = Ember.Route.extend({
selectedItem: null,
model: function () {
return posts;
},
actions: {
submit: function(){
$.ajax('/api/yourEndPoint', {type: 'POST', data: {body: this.get('selectedItem')} })
}
}
});
In your Handlebars template
<button {[action 'submit'}}>Submit</button>
In your .NET API Controller
public IHTTPActionResult Post(string body){
//.NET's Model Binder will correctly pull out the value of the body keyvalue pair.
//Now do with "body" as you will.
}
You should really look into using Ember-Data, it's freaking awesome.
You only need to set the selectionBinding="someModelAttribute" and the two way data binding will take care of setting the selected value on the model.