I'm trying delete data but I'm getting this error:
this.jobPosts.filter is not a function
PostJobIndex.vue file:
deleteJobPost: async function(jobPost) {
if (!window.confirm('Are you sure you want to delete this Job Post?')) {
return;
}
try {
await employerService.deleteJobPost(jobPost.id);
this.jobPosts = this.jobPosts.filter(obj => {
return obj.id != jobPost.id;
});
console.log(this.jobPosts);
this.$toast.success("Job Post deleted Successfully!");
} catch (error) {
console.log(error);
this.$toast.error(error.response.data.message);
}
},
I had this same issue with my Update method and I beleive it was because I was trying to map through an object or something instead of an array. In the end I used Object.keys(this.jobPosts).map for my update method and it worked:
Object.keys(this.jobPosts).map(jobPost => {
if (jobPost.id == response.data.id) {
for (let key in response.data) {
jobPost[key] = response.data[key];
}
}
});
But when I do this for Update it doesn't work:
this.jobPosts = Object.keys(this.jobPosts).filter(obj => {
return obj.id != jobPost.id;
});
UPDATED
Here is the code for loading the job posts:
loadJobPosts: async function() {
try {
const response = await employerService.loadJobPosts();
this.jobPosts = response.data;
console.log(this.jobPosts);
} catch (error) {
this.$toast.error('Some error occurred, please refresh!');
}
},
Im using Vuex for state management and I'm using services, that simply contain the axios http requests. That's where this line comes from employerService.loadJobPosts() loadJobPosts() is a function inside my employerService.js file.
I'm also using Laravel for my back end. Here is my JobPostsController.php file:
public function index()
{
$jobPosts = JobPost::all()->where('user_id', Auth::user()->id);
return response()->json($jobPosts, 200);
}
From what I've understood from your code,
this should work for removing jobPost from jobPosts
this.jobPosts = this.jobPosts.filter(obj => {
return obj.id != jobPost.id;
});
I don't know what you're expecting this to do, but it won't do anything useful and will either error or return false for everything.
this.jobPosts = Object.keys(this.jobPosts).filter(obj => {
return obj.id != jobPost.id;
});
filter exists on array types, so I would check where it's getting set and make sure it's an array.
I've included a small snippet in case it's any help.
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: "#app",
data: () => {
return {
jobPosts: [],
deleteJobId: 1
};
},
methods: {
getJobPosts() {
this.jobPosts = [{
id: 1
}, {
id: 2
}, {
id: 3
}, {
id: 4
}, {
id: 5
}];
},
deleteJob() {
if (!this.deleteJobId)
return;
this.jobPosts = this.jobPosts.filter(x => x.id !== this.deleteJobId);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button type="button" #click="getJobPosts">Get Jobs</button>
<div>
<button type="button" #click="deleteJob">Delete Job #</button>
<input type="number" v-model.number="deleteJobId" />
</div>
<ul>
<li v-for="jobPost in jobPosts">
Job Post #{{jobPost.id}}
</li>
</ul>
</div>
You have already answered your own question:
in my data() object, I have this jobPosts: [], but in the console it says Object
As for your second question:
I don't know how to return the data as an array
There are similiar topics here on SO.
I am not familiar with Laravel but assuming you have an eloquent model with JobPost in your index-function according to the docs you should use the .toArray-method:
$jobPosts = JobPost::all()->where('user_id', Auth::user()->id).toArray();
When working with plain collections the values method should do the trick of returning an array instead of an object:
$collection = collect([
10 => ['product' => 'Desk', 'price' => 200],
11 => ['product' => 'Desk', 'price' => 200]
]);
$values = $collection->values();
$values->all();
UPDATE
I just realized that your result is just a stringified JSON object that needs to be converted into an array. Just parse it before processing (take out the JSON.parse(...) if you are already taking care of it in your service), return the object properties as an array and you are good to go:)
this.jobPosts = Object.values(JSON.parse(this.jobPosts)).filter(obj => {
return obj.id != jobPost.id;
});
Related
html:
<tr
*ngFor="let workflow of auditWorkflows"
class="border-bottom"
[rowClick]="workflow | auditWorkflowRouteNavigate"
[rowClickGate]="startAuditIfNotStarted$"
>
.ts
startAuditIfNotStarted$ = new Observable((subscriber) => {
if (this.auditInProgress) {
subscriber.next(true);
subscriber.complete();
} else {
***//Here i need to get the current row item i.e workflow.id to do some additional logic***
this.confirmDialog.confirm({
header: 'Begin audit',
message: 'Are you sure you would like to start the audit?',
acceptLabel: 'Yes',
rejectLabel: 'No',
accept: () => {
this.auditInstanceService.start(this.auditId).subscribe(() => {
this.auditInProgress = true;
subscriber.next(true);
subscriber.complete();
});
},
reject: () => {
subscriber.next(false);
subscriber.complete();
}
});
}
});
directive code block:
#Input('rowClick')
options: RouterNavigateParams;
#Input('rowClickGate')
gate$?: Observable<boolean>;
private applyGateThen(callback: () => void) {
if (this.gate$) {
this.gate$.pipe(take(1)).subscribe((allow) => {
if (allow) {
callback();
}
});
} else {
callback();
}
}
Now, in the existing code , i want to pass the 'workflow' item from *ngFor into the observable, so i can do some additional logic. If i used a method as below, the method is called so many times. Is there a better way to get hold of the row item?
[rowClickGate]="provideSub(workflow)"
This is my code
<button v-if="$can('permission-a')">Add User</button>
<button v-if="$can('permission-b')">Add Employee</button>
And this is my $can method
data() {
return {
returnAccess: false
};
},
methods: {
$can(permissionName) {
let route = window.routes.permission;
let returnAccess;
axios
.get(route + `/${permissionName}`)
.then(resounse => {
if (resounse.data == 101) {
this.returnAccess = true;
}
})
.catch(error => {
this.returnAccess = false;
});
return this.returnAccess;
},
}
$can method return false for add user button and return true for add employee button. But add user button also showing because of true return for add employee button.
How can i solve this issue. Any one can help me?
Thanks in advance.
First of all you don't need to return a value
create a permissions object:
data() {
return {
permissions: {}
};
and a method like:
methods: {
$can(permissionName) {
let route = window.routes.permission;
let returnAccess;
axios
.get(route + `/${permissionName}`)
.then(resounse => {
if (resounse.data == 101) {
this.permissions.permissionName = true;
}
})
.catch(error => {
this.permissions.permissionName = false;
});
},
}
now foreach this in your created()
created() {
let permissionNames = ['a', 'b'];
permissionNames.forEach(function(permissionName) {
this.$can(permissionName) {
});
}
this way you create a object with keys as the permisson.
now in html you can simple do:
<button v-if="permission.somePermission">Add User</button>
<button v-if="permission.somePermission">Add Employee</button>
NOTE: not tested, but hope you get the idea
I've trouble finding out why my method logs the step before the actual one. So If I select 1 in a box and then 2, I'll get printed out nothing then 1.
Here is my code :
<b-form-select #input="setCadeauOrReduction(vGiftCard)" #change="calculateNet(vGiftCard)" v-if="this.cadeauOrReduction != 'reduction'" v-model="vGiftCard" id="bonCadeauSoin">
<option></option>
<option v-for="boncadeau in boncadeaus" :key="boncadeau.id" v-bind:value="boncadeau.id">
<p>N° </p>
{{boncadeau.serialNumberProduct}}
<p>|</p>
{{boncadeau.amountOfCard}}
<p>CHF</p>
</option>
</b-form-select>
This basically calls the function #change. It gives me the Gift card's id as parameter. Then the function it calls :
fetchOneBonCadeau(idToFetch)
{
axios.get('/bonCadeaus/' + idToFetch)
.then((res) => {
this.bonCadeauPourAxios = res.data
})
.catch((err) => {
console.log(err);
})
return this.bonCadeauPourAxios;
},
//Calculer montant net
calculateNet(value)
{
console.log(this.fetchOneBonCadeau(value));
if(this.vReasonReduction)
{
this.vCostNet = this.vCostBrut - this.vCostBrut * this.vReasonReduction.reductionAmount;
}
else
{
this.vCostNet = this.vCostBrut;
}
}
The console.log part always lags one step behind. I can't figure why. This is my controller if needed :
public function show($id)
{
$bonCadeau = BonCadeau::where('id', $id)->first();
return $bonCadeau;
}
Edit : normal code using the vModel binding property
fetchOneBonCadeau(idToFetch)
{
axios.get('/bonCadeaus/' + idToFetch)
.then((res) => {
this.bonCadeauPourAxios = res.data
})
.catch((err) => {
console.log(err);
})
},
//Calculer montant net
calculateNet(value)
{
this.fetchOneBonCadeau(value);
console.log(this.bonCadeauPourAxios); //Is one step behind, first value is empty
if(this.vReasonReduction)
{
this.vCostNet = this.vCostBrut - this.vCostBrut * this.vReasonReduction.reductionAmount;
}
else
{
this.vCostNet = this.vCostBrut;
}
}
I feel like vGiftCard is updated after the function "calculateNet" is called
The reason is that the result of the HTTP request returned by Axios is asynchronous, you will not obtain it right away in the fetchOneBonCadeau function.
What you can do however is return the axios promise from fetchOneBonCadeau and use it in calculateNet.
So you can implement fetchOneBonCadeau like this:
fetchOneBonCadeau(idToFetch)
{
return axios.get('/bonCadeaus/' + idToFetch)
.then(res => res.data)
.catch(err => {
console.log(err);
})
},
And calculateNet like this:
calculateNet(value)
{
this.fetchOneBonCadeau(value).then( (bonCadeauPourAxios) => {
console.log(bonCadeauPourAxios);
if(this.vReasonReduction)
{
this.vCostNet = this.vCostBrut - this.vCostBrut * this.vReasonReduction.reductionAmount;
}
else
{
this.vCostNet = this.vCostBrut;
}
});
)
}
Implementing the logic using the bonCadeauPourAxios variable in the "then" callback guaranties that the variable will have been retrieved from the backend.
I need to pass logged user id to back-end and I have vuex store so I can get my user info like {{currentUser.id}} the problem is i cannot pass it to back-end it gives me validation error that user_id is required while i have this hidden input in my form
<input type="hidden" name="user_id" :value="currentUser.id">
for normal inputs i have v-model like v-model="project.title" which is not possible to use on hidden fields.
The question here is how can I pass my user_id to back-end?
Code
<script>
import validate from 'validate.js';
export default {
data: function () {
return {
project: {
title: '',
body: '',
attachment: '',
projectclass: '',
deadline: '',
user_id: '',
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
},
errors: null
}
},
computed: {
currentUser() {
return this.$store.getters.currentUser;
}
},
methods: {
add() {
this.errors = null;
const errors = validate(this.$data.project);
if(errors) {
this.errors = errors;
return;
}
axios.post('/api/projects/new', this.$data.project)
.then((response) => {
this.$router.push('/projects');
});
}
}
}
</script>
This happens because user_id in this.$data.project dosn't get updated.
Instead of having hidden input you can just do
add() {
this.errors = null;
const errors = validate(Object.assign(this.$data.project, {user_id: this.currentUser.id}));
if(errors) {
this.errors = errors;
return;
}
axios.post('/api/projects/new', Object.assign(this.$data.project, {user_id: this.currentUser.id}))
.then((response) => {
this.$router.push('/projects');
});
}
I have a form with a "name" control.
<div class="field">
<label>Name</label>
<input ngControl="name">
<p *ngIf="name.pending">
Fetching data from the server...
</p>
<div *ngIf="!name.valid && !name.pending"
class="ui error message">Name is not valid</div>
</div>
The control is built with FormBuilder like this :
this.name = fb.control('', null, this.characterNameValidator.bind(this));
and I created a validator :
characterNameValidator(control: Control) {
let q = new Promise((resolve, reject) => {
setTimeout(() => {
if (this._characterService.isCharacterNameAlreadyExists(control.value)) {
resolve({nameCharacterAlreadyExistsError: true});
} else {
resolve(null);
}
}, 1000)
});
return q;
}
On each keystroke, my validator is called. I'm looking for a way to call the validator only after a debounce time.
I try with valueChanges(), but I understand only if I call a specific service but not in the case of validation.
Edit
Is it a good idea to manage validation manually to achieve my problem ? I don't put a validator in my control but I set errors manually on valueChanges.
this.name = fb.control('');
this.name.valueChanges.debounceTime(400).subscribe(() => {
this.characterNameValidator(this.name).then((validationResult => {
this.name.setErrors(validationResult)
}))
});
See https://github.com/angular/angular/issues/1068 for a related open issue.
If you pass a reference to the control to the validator you could use something like
this.formGp.controls['numberFld'].updateValueAndValidity();
from https://stackoverflow.com/a/33377290/217408
The official way of getting what you want is in upcoming features to form validation.
https://youtu.be/kM5QBOWrUVI?t=9m48s
However, you can manually debounce validation by subscribing to value changes, and setting your own error.
testForm.controls['name'].valueChanges
.do(
res => {
if (res) {
this.testForm.controls['name'].setErrors({loading: true});
}
}
)
.debounceTime(500)
.subscribe(
res => {
if (this.nameSub) {
this.nameSub.unsubscribe();
this.nameSub = null;
}
this.nameSub = this.http.get(apiURL + 'exist/?name=' + res).subscribe(
exists => {
this.testForm.controls['name'].setErrors({nameExists: true});
this.nameSub.unsubscribe();
this.nameSub = null;
},
error => {
if (res) {
this.testForm.controls['name'].setErrors(null);
}
this.nameSub.unsubscribe();
this.nameSub = null;
}
);
},
error => {}
);