How to remove the child when removing the parent? - javascript

I am making angular application with angular dynamic form where i am using ng-select library.
The HTML with select:
<div *ngFor="let question of questions" class="form-row {{question.class}}">
<ng-container *ngIf="question.children">
<div [formArrayName]="question.key" class="w-100">
<div *ngFor="let item of form.get(question.key).controls; let i=index" [formGroupName]="i" class="row mt-1">
<div *ngFor="let item of question.children" class="{{item.class}} align-middle">
<div class="w-100">
<dynamic-form-builder [question]="item" [index]="i" [form]="form.get(question.key).at(i)"></dynamic-form-builder>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-6 col-sm-12 col-lg-6 col-md-6">
<div class="form-label-group" *ngIf="showTemplateDropdown">
<ngi-select placeholder="Select Template" [required]="true" [hideSelected]="false" [multiple]="true" [items]="templateList"
dropdownPosition="down" bindLabel="name" bindValue="id" (add)="getTemplateValues($event)" (remove)="onRemove($event)">
</ngi-select>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-6 col-sm-12 col-lg-6 col-md-6">
</div>
<div class="col-6 col-sm-12 col-lg-6 col-md-6 text-right">
<div class="btn-group float-right">
<button class="btn btn-primary btn-round btn-fab mat-raised-button" mat-min-fab="" mat-raised-button="" type="button"
(click)="addControls('template_properties')">
<span class="mat-button-wrapper"><i class="material-icons mt-2">add</i></span>
<div class="mat-button-ripple mat-ripple" matripple=""></div>
<div class="mat-button-focus-overlay"></div>
</button>
<button class="btn btn-primary btn-round btn-fab mat-raised-button" mat-min-fab="" mat-raised-button="" type="button"
(click)="removeControls('template_properties')">
<span class="mat-button-wrapper"><i class="material-icons mt-2">remove</i></span>
<div class="mat-button-ripple mat-ripple" matripple=""></div>
<div class="mat-button-focus-overlay"></div>
</button>
</div>
</div>
</div>
</div>
</div>
</ng-container>
<ng-container *ngIf="!question.children">
<div class="w-100">
<dynamic-form-builder [question]="question" [form]="form"></dynamic-form-builder>
</div>
</ng-container>
</div>
Here the [items]="templateList" has the following,
[{"id":"5bebba2c20ccc52871509d56","name":"Template One"},
{"id":"5bebba5720ccc52871509d57","name":"Template Two"},
{"id":"5bebba8d20ccc52871509d5d","name":"Template Three"}]
I am having (change)="getTemplateValues($event)" event for detecting each change happen when we select an item from dropdown.
The change event function Edited,
getTemplateValues(e) {
this.dynamicFormService.getRest("url" + '/' + e.id").subscribe(res => {
try {
if (res.status === "true") {
res.data.template_properties.forEach(element => {
this.templateArray.push(element);
});
this.form = this.qcs.toFormGroup(this.questions);
for (let i = 0; i < this.templateArray.length; i++) {
this.addControls('template_properties');
}
let propertiesArray = [];
this.templateArray.forEach(element => {
propertiesArray.push(element);
});
this.form.patchValue({
'template_properties': propertiesArray
});
} else {
}
}
catch (error) {
}
})
}
console.log(this.propertiesArray) gives the following,
[{"property_name":"Property one","property_type":4,"property_required":true,"property_origin":1},{"property_name":"Property one","property_type":5,"property_required":true,"property_origin":1}]
In the below image i have deleted template three but the template three properties still showing in it..
Here first i am filtering the data first and ignoring the duplicates and each time i am sending the newly selected values alone to the service and fetching the data related to the id element.id.
And using this.addControls('template_properties') to make open the number of rows, and elements will get patched to the form template_properties.
this.form.patchValue({
'template_properties': propertiesArray
});
As of now everything working fine..
The problem actually arise from here:
If we delete a selected list from dropdown, (say i have selected all three template and i have deleted the template two then that particular template's template_properties needs to get deleted..
I have tried with (remove)="onRemove($event)" but its not working because while remove data, the (change) function also calls..
How can i remove the template_properties with this.removeControls('template_properties'); of particular deleted template name in the change event or remove event..
Remove Function:
onRemove(e) {
console.log(e);
this.dynamicFormService.getRest("url" + '/' + e.value.id").subscribe(res => {
try {
if (res.status === "true") {
for (let i = 0; i < res.data.template_properties.length; i++) {
this.removeControls('template_properties');
}
} else {
}
}
catch (error) {
}
})
}
Remove Control:
removeControls(control: string) {
let array = this.form.get(control) as FormArray;
console.log(array)
array.removeAt(array.length);
}
console.log(array) gives,

It should be pretty easy fix. Use (add) instead of (change) in ngi-select.
onRemove(e) {
console.log(e);
this.dynamicFormService.getRest("url" + '/' + e.value.id").subscribe(res => {
try {
if (res.status === "true") {
this.form = this.qcs.toFormGroup(this.questions);
// Issue is here, you should remove only specific record
// which is being passed from function `e`
for (let i = 0; i < res.data.template_properties.length; i++) {
this.removeControls('template_properties');
}
let propertiesArray = [];
this.templateArray.forEach(element => {
propertiesArray.push(element);
});
this.form.patchValue({
'template_properties': propertiesArray
});
} else {
}
}
catch (error) {
}
})
}
Pass the index in removeControls where you want to remove the element from.
removeControls(control: string, index:number) {
let array = this.form.get(control) as FormArray;
console.log(array)
array.removeAt(index);
}
console.log(array) gives,

Related

How do I get this div to show again using JavaScript

I have made a TODO app and added a counter to keep a count of the items in the list. If the counter hits zero, I've set it to re-show a message 'You currently have no tasks. Use the input field above to start adding.'
if(count === 0){
noTasksText.classList.remove('d-none');
}
In the console I print out the div and it doesn't have d-none in the class list any more which is what I want, however, in the actual DOM it does.
Here is a full example - https://codepen.io/tomdurkin/pen/LYdpXKJ?editors=1111
I really can't seem to work this out. I can't seem to interact with that div when the counter becomes zero, however I can get console logs etc to show when expected.
Any help would be appreciated!
const mainInput = document.querySelector('#main-input');
const todoContainer = document.querySelector('#todo-container');
const errorText = document.querySelector('#js-error');
const noTasksText = document.querySelector('.js-no-tasks')
let tasks = [];
let count = 0;
// focus input on load
window.onload = () => {
mainInput.focus();
const storedTasks = JSON.parse(localStorage.getItem('tasks'));
if (storedTasks != null && storedTasks.length > 0) {
// set count to number of pre-existing items
count = storedTasks.length
// hide the 'no tasks' text
noTasksText.classList.add('d-none');
// overwrite tasks array with stored tasks
tasks = storedTasks;
tasks.forEach(task => {
// Build the markup
const markup = `
<div class="js-single-task single-task border-bottom pt-2 pb-2">
<div class="row">
<div class="col d-flex align-items-center js-single-task-name">
<h5 class="mb-0" data-title="${task}">${task}</h5>
</div>
<div class="col d-flex justify-content-end">
<button class="js-remove-task d-block btn btn-danger">Remove Item</button>
</div>
</div>
</div>`;
// Append it to the container
todoContainer.innerHTML += markup;
});
} else {
if (noTasksText.classList.contains('d-none')) {
noTasksText.classList.remove('d-none');
}
}
};
// event listener for 'enter on input'
mainInput.addEventListener("keydown", e => {
// if error is showing, hide it!
if (!errorText.classList.contains('d-none')) {
errorText.classList.add('d-none');
}
if (e.key === "Enter") {
// Get the value of the input
let inputValue = mainInput.value;
if (inputValue) {
// Build the markup
const markup = `
<div class="js-single-task border-bottom pt-2 pb-2">
<div class="row">
<div class="col d-flex align-items-center js-single-task-name">
<h5 class="mb-0" data-title="${inputValue}">${inputValue}</h5>
</div>
<div class="col d-flex justify-content-end">
<button class="js-remove-task d-block btn btn-danger">Remove Item</button>
</div>
</div>
</div>`;
// hide 'no tasks' text
noTasksText.classList.add('d-none');
// Append it to the container
todoContainer.innerHTML += markup;
// Push value to 'tasks' array
tasks.push(inputValue);
// Put in localStorage
textTasks = JSON.stringify(tasks);
localStorage.setItem("tasks", textTasks);
// Reset the value of the input field
mainInput.value = '';
// add 1 to the count
count++
} else {
// Some very basic validation
errorText.classList.remove('d-none');
}
}
});
// remove task
todoContainer.addEventListener('click', (e) => {
// Find the button in the row that needs removing (bubbling)
const buttonIsDelete = e.target.classList.contains('js-remove-task');
if (buttonIsDelete) {
// Remove the HTML from the screen
e.target.closest('.js-single-task').remove();
// Grab the name of the single task
let taskName = e.target.closest('.js-single-task').querySelector('.js-single-task-name h5').getAttribute('data-title');
// filter out the selected word
tasks = tasks.filter(item => item != taskName);
textTasks = JSON.stringify(tasks);
localStorage.setItem("tasks", textTasks);
// update counter
count--
// check if counter is zero and re-show 'no tasks' text if true
if (count === 0) {
noTasksText.classList.remove('d-none');
console.log(noTasksText);
}
}
});
body {
background: #e1e1e1;
}
<div class="container">
<div class="row d-flex justify-content-center mt-5">
<div class="col-10 col-lg-6">
<div class="card p-3">
<h2>To dos</h2>
<p>
Use this app to keep a list of things you need to do
</p>
<input class="form-control" id="main-input" type="text" placeholder="Type your todo and hit enter..." class="w-100" />
<small id="js-error" class="text-danger d-none">
Please type a value and press enter
</small>
<hr />
<h4 class="mb-5">Your 'To dos'</h4>
<div id="todo-container">
<!-- todos append in here -->
<div class="js-no-tasks">
<small class="d-block w-100 text-center mb-3">
<i>
You currently have no tasks. Use the input field above to start adding
</i>
</small>
</div>
</div>
</div>
<!-- /card -->
</div>
</div>
</div>
Upon setting innerHTML by using += innerHTML the node noTasksText is lost, because browser processes the whole new set innerHTML and creates new objects. You can either retrieve noTasksText again after that, or append nodes using todoContainer.appendChild. I forked your pen and solved it with the latter solution.
https://codepen.io/aghosey/pen/wvmGwWd
You can do the following, it will work (here innerHTML is changing the DOM, so I added an extra function to recalculate elements after DOM is changed due to innerHTML):
var mainInput = document.querySelector("#main-input");
var todoContainer = document.querySelector("#todo-container");
var errorText = document.querySelector("#js-error");
var noTasksText = document.querySelector(".js-no-tasks");
let tasks = [];
let count = 0;
function getAllElements() {
mainInput = document.querySelector("#main-input");
todoContainer = document.querySelector("#todo-container");
errorText = document.querySelector("#js-error");
noTasksText = document.querySelector(".js-no-tasks");
}
// focus input on load
window.onload = () => {
mainInput.focus();
var storedTasks = JSON.parse(localStorage.getItem("tasks"));
if (storedTasks != null && storedTasks.length > 0) {
// set count to number of pre-existing items
count = storedTasks.length;
// hide the 'no tasks' text
noTasksText.classList.add("d-none");
// overwrite tasks array with stored tasks
tasks = storedTasks;
tasks.forEach((task) => {
// Build the markup
const markup = `
<div class="js-single-task single-task border-bottom pt-2 pb-2">
<div class="row">
<div class="col d-flex align-items-center js-single-task-name">
<h5 class="mb-0" data-title="${task}">${task}</h5>
</div>
<div class="col d-flex justify-content-end">
<button class="js-remove-task d-block btn btn-danger">Remove Item</button>
</div>
</div>
</div>`;
// Append it to the container
todoContainer.innerHTML += markup;
getAllElements();
});
} else {
if (noTasksText.classList.contains("d-none")) {
noTasksText.classList.remove("d-none");
}
}
};
// event listener for 'enter on input'
mainInput.addEventListener("keydown", (e) => {
// if error is showing, hide it!
if (!errorText.classList.contains("d-none")) {
errorText.classList.add("d-none");
}
if (e.key === "Enter") {
// Get the value of the input
let inputValue = mainInput.value;
if (inputValue) {
// Build the markup
const markup = `
<div class="js-single-task border-bottom pt-2 pb-2">
<div class="row">
<div class="col d-flex align-items-center js-single-task-name">
<h5 class="mb-0" data-title="${inputValue}">${inputValue}</h5>
</div>
<div class="col d-flex justify-content-end">
<button class="js-remove-task d-block btn btn-danger">Remove Item</button>
</div>
</div>
</div>`;
// hide 'no tasks' text
noTasksText.classList.add("d-none");
// Append it to the container
todoContainer.innerHTML += markup;
getAllElements();
// Push value to 'tasks' array
tasks.push(inputValue);
// Put in localStorage
textTasks = JSON.stringify(tasks);
localStorage.setItem("tasks", textTasks);
// Reset the value of the input field
mainInput.value = "";
// add 1 to the count
count++;
} else {
// Some very basic validation
errorText.classList.remove("d-none");
}
}
});
// remove task
todoContainer.addEventListener("click", (e) => {
// Find the button in the row that needs removing (bubbling)
const buttonIsDelete = e.target.classList.contains("js-remove-task");
if (buttonIsDelete) {
// Remove the HTML from the screen
e.target.closest(".js-single-task").remove();
// Grab the name of the single task
let taskName = e.target
.closest(".js-single-task")
.querySelector(".js-single-task-name h5")
.getAttribute("data-title");
// filter out the selected word
tasks = tasks.filter((item) => item != taskName);
textTasks = JSON.stringify(tasks);
localStorage.setItem("tasks", textTasks);
// update counter
count--;
// check if counter is zero and re-show 'no tasks' text if true
if (count === 0) {
noTasksText.classList.remove("d-none");
console.log(noTasksText);
}
}
});
body {
background: #e1e1e1;
}
<div class="container">
<div class="row d-flex justify-content-center mt-5">
<div class="col-10 col-lg-6">
<div class="card p-3">
<h2>To dos</h2>
<p>
Use this app to keep a list of things you need to do
</p>
<input class="form-control" id="main-input" type="text" placeholder="Type your todo and hit enter..." class="w-100" />
<small id="js-error" class="text-danger d-none">
Please type a value and press enter
</small>
<hr />
<h4 class="mb-5">Your 'To dos'</h4>
<div id="todo-container">
<!-- todos append in here -->
<div class="js-no-tasks">
<small class="d-block w-100 text-center mb-3">
<i>
You currently have no tasks. Use the input field above to start adding
</i>
</small>
</div>
</div>
</div>
<!-- /card -->
</div>
</div>
</div>

filtering category with detach()

Help me with detach () function.
I figured out how it works, but I need help in applying it, in my case now it deletes all the selected categories, but you need to do the opposite so that all categories except the selected one are deleted. Is it necessary to somehow put everything except the selected one into a class and use detach () or what is better?
html
<div class="blog-filter">
<div class="blog-filter_item active js-filter-blog-list" data-filter="all">All</div>
</div>
<div class="blog-filter-container">
<div class="container">
<h1 class="blog-filter-title">Choose Category</h1>
<div class="item-wrapper">
<div class="blog-filter_item active" data-filter="all">All</div>
#foreach($categories as $category)
<div class="blog-filter_item" data-filter=".category_{{$category->id}}">{{ $category->title }} ({{ $category->articles_count }})</div>
#endforeach
</div>
</div>
</div>
<div class="blog-list">
#foreach($articles as $article)
<div class="blog-article category_{{ $article->blog_category_id }}">
<h2 class="blog-article__title">{{ $article->title }}</h2>
</div>
#endforeach
</div>
js
var divs;
$('.blog-article').each(function(i){
$(this).data('initial-index', i);
});
document.querySelectorAll('.blog-filter_item').forEach(el => {
el.addEventListener('click', () => {
document
.querySelector('.blog-filter_item.active')
.classList.remove('active');
el.classList.add('active');
var dataFilter = $(el).attr('data-filter');
$(divs).appendTo('.blog-list').each(function(){
var oldIndex = $(this).data('initial-index');
$('.blog-article').eq(oldIndex).before(this);
});
divs = null;
if (dataFilter == 'all') {
$('.blog-article').show();
}
else {
divs = $(dataFilter).detach();
$('.blog-article').show();
}
});
});
Solution:
divs = $('.blog-article').not(dataFilter).detach();

How to filter an Array with Checkboxes items?

I want to filter my checkboxes I search it on internet there was information but I couldn't work it with my code.
This is the webpage
I want when you click on the checkbox it must be same as the category.
This is some code of the checkbox:
<div>
<input class="form-check-input checkboxMargin" type="checkbox" value="All" v-model="selectedCategory">
<p class="form-check-label checkboxMargin">All</p>
</div>
This is my grey box layout:
<div class="col-sm-12 col-md-7">
<div class="card rounded-circle mt-5" v-for="item of items" :key="item['.key']">
<div>
<div class="card-body defaultGrey">
<h5 class="card-title font-weight-bold">{{ item.name }}</h5>
<div class="row mb-2">
<div class="col-sm ">
<div class="row ml-0"><h6 class="font-weight-bold">Job:</h6><h6 class="ml-1">{{ item.job }}</h6></div>
<div class="row ml-0"><h6 class="font-weight-bold">Category:</h6><h6 class="ml-1">{{ item.categories }}</h6></div>
<div class="row ml-0"><h6 class="font-weight-bold">Location:</h6><h6 class="ml-1">{{ item.location }}</h6></div>
<div class="row ml-0"><h6 class="font-weight-bold">Niveau:</h6><h6 class="ml-1">{{ item.niveau }}</h6></div>
<div class="row ml-0"><h6 class="font-weight-bold">Availability:</h6><h6 class="ml-1">{{ item.availability }}</h6></div>
<h6>{{ item.info }}</h6>
<div class="row ml-0"><h6 class="font-weight-bold">Posted:</h6><h6 class="ml-1">{{ item.user }}</h6></div>
</div>
</div>
<div class="row">
<div class="col-xs-1 ml-3" v-if="isLoggedIn">
<router-link :to="{ name: 'InternshipDetails', params: {id: item['.key']} }" class="btn bg-info editbtn">
Details
</router-link>
</div>
<div class="col-xs-1 ml-3 mr-3" v-if="isLoggedIn && item.user == currentUser">
<router-link :to="{ name: 'Edit', params: {id: item['.key']} }" class="btn btn-warning editbtn">
Edit
</router-link>
</div>
<div class="col-xs-1" v-if="isLoggedIn && item.user == currentUser">
<button #click="deleteItem(item['.key'])" class="btn btn-danger dltbtn">Delete</button>
</div>
</div>
</div>
</div>
</div>
</div>
And I have my object here but how can I filter my grey boxes with category:
selectedCategory: []
Use computed properties:
computed: {
filteredItems(){
if(this.selectedCategory.length == 0) return this.items;
return this.items.filter(el => {
for(let i = 0; i < this.selectedCategory.length; i++){
if(el.categories == this.selectedCategory[i]) return el;
}
});
}
}
Then you go for v-for="item of filteredItems"
I didnt tested it. If you provide me more code i could help you more
You need to create one-way binding between your CategoryCheckBox component and your ListCard component.
Because you provided separated code when I can not reproduce it to give you a solution based on your own, I suggest this example to explain my solution.
Step One:
You have many ways to CRUD your items using a Plugins or Vuex or global instance, in my example I used global instance in main.js
Vue.prototype.$myArray = ["Books", "Magazines", "Newspaper"];
I assume you created your items data in the ListCards component
Step Two:
You need to add #change event in your checkbox to handle checked and unchecked states. I used static data (Book) for value.
<label>
<input type="checkbox" value="Books" #change="handleCategory($event)" /> Books
Now, let's implement handleCategory method, but before that, as we know that Checkbox and ListCards are independents which means we need to define a bus to create event communication between them and this is your issue so we define the bus inside the main.js
Vue.prototype.$bus = new Vue({});
Now we define handleCategory like this :
methods: {
handleCategory(e) {
this.$bus.$emit("checkCategory", e);
}
}
Step Three:
How can our ListCards listen to this event ?
By call $bus.$on(..) when the component is created ( Hope you know what Vue lifecycle methods mean )
created() {
this.$bus.$on("checkCategory", e => this.checkCategory(e));
},
When the user click the check box the component runs handleCategory then runs checkCategory inside ListCard.
Inside my ListCard, I have categories and originalCategories as data
data() {
return {
categories: this.$myArray,
originalCategories: this.$myArray
};
},
and a template :
<ul v-for="(category,index) in categories" :key="index">
<CategoryItem :categoryName="category" />
</ul>
and a created method ( lifecycle )
created() {
// $bus is a global object to communicate between components
this.$bus.$on("checkCategory", e => this.checkCategory(e));
},
and our filtering methods :
methods: {
checkCategory(e) {
let target = e.target;
let value = e.target.value;
target.checked
? this.filterCatergories(value)
: (this.categories = this.originalCategories);
},
filterCatergories(value) {
this.categories = this.categories.filter(val => val === value);
}
}
What's important for you is :
this.categories.filter(val => val === value); //will not do nothing
const categories=this.categories.filter(val => val === value); //will update the view.
And you can change the code or make it better and simple.
#Update
You can also use computed properties but because we have a parameter here which is the category name we need get and set.
computed: {
filteredItems: {
get: function() {
if (this.selectedCategory.length == 0) return this.items;
return this.items.filter(value => {
for (const category of this.selectedCategory) {
if (value == category) return value;
}
});
},
set: function(category) {
this.selectedCategory.push(category);
}
}
},
methods: {
checkCategory(e) {
let target = e.target;
let value = e.target.value;
target.checked
? (this.filteredItems = value)
: this.selectedCategory.pop(value);
}
}

change specific elemnt of ngFor where list is changes

i have this HTML for show list of users :
<div *ngFor="let item of users " [ngClass]="{'highlight': item.isDeleted }"
class="d-flex selected-list-items mt-3">
<div class="col-md-5 col-lg-5 col-xs-5 col-sm-5 col-xl-5">
<label>{{item.displayName}}</label>
</div>
<div class="col-md-5 col-lg-5 col-xs-5 col-sm-5 col-xl-5">
<label> {{ getEnumTranslate(item.title)}}</label>
</div>
<div class="justify-content-center col-md-2 col-lg-2 col-xs-2 col-sm-2 col-xl-2">
<button (click)="deleteUser(item.userId)" mat-button>
<mat-icon aria-label="Delete" color="accent">delete</mat-icon>
</button>
</div>
</div>
and i create a validation with private transport: BehavorSubject, for do this :
when the transport is changes must be execute this code :
this.transport.listValue$.subscribe(data => {
if (data != null) {
data.forEach(element => {
let user = this.users.find(x => x.userId = element);
if (user != null) {
user.isDeleted = true;
}
});
}
});
and in html change the background color of find user in this code let user = this.users.find(x => x.userId = element); .
now my problem is here :
when transport is change it run code for change background and find that user but it just change background of first element in this HTML code , specific user in the Third element but it change first element In the event that need change Third element in HTML .
how can i solve this problem ?
I have updated the code that should work for your scenario. Here I am mutating the actual data inside users array. Please check and let me know if it resolves your issue.
this.transport.listValue$.subscribe(data => {
if(data != null) {
for (const user of this.users) {
if(data.includes(user.userId)) {
user.isDeleted = true
}
}
}
});

Problem with Axios PUT and GET request, sometimes work well, sometimes doesn't

I'm using Axios to fetch data from a server, I'm trying to do a PUT request and I need to get data info from 3 tables in order to fill the form, when I do the PUT it sometimes works and sometimes doesn't, but when I open the browser terminal to debug the problem, the PUT request always works, also I notice that another component without nested GET requests always works fine, but I can't fetch the data from the server if those GET requests aren't nested.
Here is my script code, I don't know what I'm doing wrong with this.
<template>
<div class="container-fluid">
<div style="margin:40px;background-color:rgba(255, 255, 255, 0.7);">
<div class="row">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item">Usuarios</li>
<li class="breadcrumb-item">Roles</li>
<li class="breadcrumb-item"><a v-bind:href="rol_url">{{rol_name}}</a></li>
<li class="breadcrumb-item active" aria-current="page">Editar Rol</li>
</ol>
</nav>
</div>
<div class="row">
<div class="col-md-8 offset-md-2" style="margin-bottom:80px;">
<div class="row">
<div class="col">
<button onclick="window.history.back();" class="btn btn-primary" style="background:#003e1e;border-color:#003e1e;">
<font-awesome-icon icon="arrow-left" size="lg"></font-awesome-icon>
</button>
</div>
</div>
<div> </div>
<div class="row justify-content-center">
<div class="col-5 align-self-center">
<form>
<div class="form-group">
<label for="rolName">Nombre del rol:</label>
<input v-model="rol_name" type="text" class="form-control" id="rolName" aria-describedby="rolName" placeholder="Nombre">
</div>
<div class="form-group">
<label for="rolModules">Modulos del rol:</label>
<multiselect v-model="rol_mod" :options="modules" :multiple="true" :close-on-select="true" :clear-on-select="false" :hide-selected="true" :preserve-search="true" placeholder="Seleccione los modulos" label="name" track-by="modulo" :preselect-first="false">
</multiselect>
</div>
<div v-for='(module, index) in rol_mod' :key='index' class="form-group">
<label for="rolModules">Permisos de {{module.name}}</label>
<multiselect v-model="module.permisos" :options="permits" :multiple="true" :close-on-select="true" :clear-on-select="false" :hide-selected="true" :preserve-search="true" placeholder="Seleccione los permisos del modulo" label="name" track-by="_id" :preselect-first="false">
</multiselect>
</div>
<div class="form-group">
<label for="rolStates">Estado del rol:</label>
<multiselect v-model="rol_state" :options="states" track-by="name" label="name" :searchable="false" :close-on-select="true" :show-labels="true" :placeholder="rol_state_get">
</multiselect>
</div>
<div class="form-group">
<label for="permitDescription">DescripciĆ³n:</label>
<textarea v-model="rol_description" class="form-control" aria-label="permitDescription"
placeholder="DescripciĆ³n" :rows="6" :max-rows="10"></textarea>
</div>
<div> </div>
<div class="row justify-content-center">
<div class="col-4 text-center">
<button class="btn btn-primary" v-on:click="submit()" style="background:#003e1e;border-color:#003e1e;">
<font-awesome-icon icon="save" size="lg"></font-awesome-icon>
Guardar
</button>
</div>
<div class="col-4 text-center">
<a class="btn btn-primary" style="background:#003e1e;border-color:#003e1e;" v-bind:href="rol_url">
<font-awesome-icon icon="times-circle" size="lg"></font-awesome-icon>
Cancelar
</a>
</div>
</div>
<div> </div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
const axios = require('axios');
var API_IP = process.env.VUE_APP_API_IP
export default {
components: {
Multiselect
},
data () {
return {
rol_auditoria: {},
modules: [],
permits: [],
rol_name: "",
rol_state: "",
rol_state_get: "",
rol_description: '',
states: [
{ name: "Activo", activo: "true" },
{ name: "Inactivo", activo: "false" }
],
rol_mod: [],
rol_url: ""
}
},
mounted () {
axios
.get(API_IP+'/rol/'+this.$route.params.id)
.then(response => {
this.rol_auditoria = response.data.data.auditoria;
this.rol_name = response.data.data.nombre;
this.rol_state = response.data.data.activo;
response.data.data.activo? this.rol_state_get="Activo" : this.rol_state_get="Inactivo";
this.rol_description = response.data.data.descripcion
this.rol_id = response.data.data._id
this.rol_url = "/roles/"+response.data.data._id
for (var k in response.data.data.modulos){
var mod_info = {}
console.log(response.data.data.modulos[k].modulo.nombre);
mod_info["_id"] = response.data.data.modulos[k]._id
mod_info["modulo"] = { "_id" : response.data.data.modulos[k].modulo._id }
mod_info["name"] = response.data.data.modulos[k].modulo.nombre
var mod_per = []
for (var j in response.data.data.modulos[k].permisos){
var perms = {}
perms["_id"] = response.data.data.modulos[k].permisos[j]._id
perms["name"] = response.data.data.modulos[k].permisos[j].nombre
mod_per.push(perms)
}
mod_info["permisos"] = mod_per
this.rol_mod.push(mod_info)
}
axios
.get(API_IP+"/module/")
.then(response => {
for(var k in response.data.data){
var mod = {}
mod["modulo"] = { "_id" : response.data.data[k]._id }
mod["name"] = response.data.data[k].nombre;
this.modules.push(mod);
}
axios
.get(API_IP+"/permit/")
.then(response => {
for(var k in response.data.data){
var per = {}
per["name"] = response.data.data[k].nombre;
per["_id"] = response.data.data[k]._id;
this.permits.push(per);
}
});
});
})
},
methods: {
submit: function() {
axios
.put(API_IP+"/rol/"+this.$route.params.id, {
auditoria: this.rol_auditoria,
activo: this.rol_state.activo,
_id: this.rol_id,
nombre: this.rol_name,
descripcion: this.rol_description,
modulos: this.rol_mod
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
this.$router.push({ name: 'showrol', params: { id: this.rol_id} });
}
}
}
</script>
This may be a long shot without having information from the console output and the actual info or errors being returned from the GET requests, but I noticed a lot of "this" use on your code.
You are double nesting axios calls, which are async. "this" tends to be hard to debug in javascript, even if youre using arrow functions which should be relatively safe.
Please try to add:
let self = this;
Before you start your GET requests, and use "self" instead of "this" inside your promises.
This may be obvious, but I dont see you calling this.submit() anywhere in your code. Where inside the GET callbacks are you calling SUBMIT for the PUT request?

Categories