Bind specific checkbox to disable specific dropdown in VueJS? - javascript

I have a table, each row has a checkbox, name, another checkbox, and dropdown. I want to have the dropdown disabled by default, and only enable it when check the first checkbox.
Here's the HTML:
<tbody>
<tr v-for="item in Items" v-bind:id="item.ID">
<td>
<!-- check this checkbox and enable/disable the dropdown -->
<input type="checkbox" v-on:click="onSelect($event)" v-model="item.Selected" />
</td>
<td>
{{ item.Name }}
</td>
<td>
<input type="checkbox" v-model="item.isActive" /><
<td>
<!-- enabled/disabled depending on if checkbox is checked -->
<select v-bind:disabled="">
<option value="foo">foo</option>
<option value="bar">bar</option>
</select>
</td>
</tr>
</tbody>
Currently, the onSelect($event) method will check the second checkbox in the same row when checked.
Here's my JavaScript:
var vm = new Vue({
el: '#app',
data: {
items: items
},
methods: {
onSelect: function (event, id) {
setTimeout(function () {
var idx = $(event.target).closest('tr').index();
if (items[idx].Selected) {
items[idx].isActive = true;
}
}, 100);
}
}
});
Is there a way to bind the enabling/disabling of the dropdown to a checkbox with VueJS 2/JavaScript/jQuery?

You don't actually need to use jQuery or events for this, rather you can simply use Vue's data binding for this. Simply set v-model="item.Selected" on the first checkbox, and then on the select, set v-bind:disabled="!item.Selected".
HTML:
<!-- index.html -->
<div id="app">
<table>
<tbody>
<tr v-for="item in items">
<td>
<!-- check this checkbox and enable/disable the dropdown -->
<input type="checkbox" v-model="item.Selected"/>
</td>
<td>
{{ item.Name }}
</td>
<td>
<!-- enabled/disabled depending on if checkbox is checked -->
<select v-bind:disabled="!item.Selected">
<option value="foo">foo</option>
<option value="bar">bar</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
JavaScript:
// app.js
const vm = new Vue({
el: '#app',
data() {
return {
items: [
{ ID: 1, Name: 'name 1', isAcitve: false, Selected: false },
{ ID: 2, Name: 'name 2', isAcitve: false, Selected: false },
{ ID: 3, Name: 'name 3', isAcitve: false, Selected: false },
]
}
},
})
I've attached a pen which displays this.

Related

How to parent tr checked if child tr is checked

Info: I am try to make a nested table. The table have parent && child rows.
The feature
I want to make if user click on parent tr>input:checkbox the all child tr>input:checkbox checked.
I want to know if any parent-tr child-tr checkbox is checked then parent-tr also checked.
Parent tr automatically checked If user checked child input:checkbox checked one by one manually even if i checked only one. if under the parent child unchecked parents also unchecked.
function childRowCheck() {
const childRow = $("tr#child-tr input:checked")
childRow.each(function (i, item) {
let tbody = $(this).parents("tbody");
tbody.children("tr#parent-tr").eq(i).find(":checkbox").attr('checked', $(this).is(':checked'));
})
}
childRowCheck();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table">
<tbody>
<!-- BEGIN::Subject loop -->
<tr id="parent-tr" class="parent-tr" data-id="2">
<td class="action">
<input type="checkbox" name="checkbox[2]" value="2" id="id_subject">
</td>
</tr>
<!-- END::Subject loop -->
<!-- BEGIN::Tickers loop -->
<tr id="child-tr" class="child-tr" data-ticker-id="6" data-subject-id="2">
<td class="action">
<input type="checkbox" name="tikcer" id="id_ticker">
</td>
</tr>
<tr id="child-tr" class="child-tr" data-ticker-id="7" data-subject-id="2">
<td class="action">
<input type="checkbox" name="tikcer" id="id_ticker">
</td>
</tr>
<tr id="child-tr" class="child-tr" data-ticker-id="8" data-subject-id="2">
<td class="action">
<input type="checkbox" name="tikcer" id="id_ticker">
</td>
</tr>
<!-- END::Tickers loop -->
<!-- BEGIN::Subject loop -->
<tr id="parent-tr" class="parent-tr" data-id="3">
<td class="action">
<input type="checkbox" name="checkbox[3]" value="3" id="id_subject">
</td>
<td colspan="6"></td>
</tr>
<!-- END::Subject loop -->
<!-- BEGIN::Tickers loop -->
<tr id="child-tr" class="child-tr" data-ticker-id="9" data-subject-id="3">
<td class="action">
<input type="checkbox" name="tikcer" id="id_ticker">
</td>
</tr>
<tr id="child-tr" class="child-tr" data-ticker-id="10" data-subject-id="3">
<td class="action">
<input type="checkbox" name="tikcer" id="id_ticker">
</td>
</tr>
<tr id="child-tr" class="child-tr" data-ticker-id="11" data-subject-id="3">
<td class="action">
<input type="checkbox" name="tikcer" id="id_ticker">
</td>
</tr>
<!-- END::Tickers loop -->
</tbody>
</table>
You have much better control of your application, if you control the data and not the UI:
create a data structure that best suits the relation(s) between the elements
create a template that can be re-used to populate the DOM
The main benefit of the solution below is that you always have a correct state that you can use (e.g. submit); also the shape of the data does not change: the input & output of your process look the same.
I put one more level of depth (so parent->child->grandchild) to show that it works quite nice with n levels hierarchy.
const data = [{
id: "parent-tr-1",
label: "Parent 1",
checked: false,
children: [{
id: "child-tr-1-1",
label: "Child 1_1",
checked: false,
children: [
{
id: "child-tr-1-1-1",
label: "Child 1_1_1",
checked: false,
children: [],
},
{
id: "child-tr-1-1-2",
label: "Child 1_1_2",
checked: false,
children: [],
}
],
},
{
id: "child-tr-1-2",
label: "Child 1_2",
checked: false,
children: [],
},
]
},
{
id: "parent-tr-2",
label: "Parent 2",
checked: false,
children: [{
id: "child-tr-2-1",
label: "Child 2_1",
checked: false,
children: [],
},
{
id: "child-tr-2-2",
label: "Child 2_2",
checked: false,
children: [],
},
{
id: "child-tr-2-3",
label: "Child 2_3",
checked: false,
children: [],
},
]
},
]
const getRowsFlat = (data) => data.reduce((a, c) => [...a, c, ...getRowsFlat(c.children)], [])
const setChecked = (id, data, checkedState) => {
data.forEach(e => {
// setting children checked if parent is clicked
if (e.id === id || id === "parent-force") {
e.checked = checkedState ?? !e.checked
if (e.id === id) {
setChecked("parent-force", e.children, e.checked)
} else {
setChecked("parent-force", e.children)
}
} else {
setChecked(id, e.children)
}
// if ANY of the children is set to checked, parent should be checked
if (e.children.length && e.children.some(({
checked
}) => checked)) {
e.checked = true
}
// if NONE of the children is set to checked, parent should not be checked
if (e.children.length && e.children.every(({
checked
}) => !checked)) {
e.checked = false
}
})
}
// row HTML template
const getRowHtml = (data) => {
return `
<tr>
<td>
<input type="checkbox" id="${data.id}" ${ data.checked ? "checked" : null }/>
<label for="${data.id}">${data.label}</label>
</td>
</tr>
`
}
// table update function
const updateContainer = (container) => (data) => {
container.innerHTML = data.map(getRowHtml).join("")
}
// initialization
const tbody = document.getElementById("tbody")
const updateTableBody = updateContainer(tbody)
// first render
setChecked(null, data) // if run with id NULL, then only the children can affect the parent
updateTableBody(getRowsFlat(data))
jQuery(document).ready(function($) {
$("#table").on("click", "input", function() {
const thisId = $(this).attr("id")
setChecked(thisId, data)
updateTableBody(getRowsFlat(data))
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table">
<tbody id="tbody"></tbody>
</table>
You can not use the same id multiple times.
Check following code with class instead of id:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<!-- parent -->
<tr>
<td>
<input type="checkbox" name="subject" class="subject1" />Parent
</td>
<td colspan="3"></td>
</tr>
<!-- child -->
<tr>
<td><input type="checkbox" name="ticker" class="ticker1" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" class="ticker1" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" class="ticker1" />Child</td>
</tr>
<!-- parent -->
<tr>
<td>
<input type="checkbox" name="subject" class="subject2" />Parent
</td>
<td colspan="3"></td>
</tr>
<!-- child -->
<tr>
<td><input type="checkbox" name="ticker" class="ticker2" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" class="ticker2" />Child</td>
</tr>
<tr>
<td><input type="checkbox" name="ticker" class="ticker2" />Child</td>
</tr>
</tbody>
</table>
<script>
$(document).ready(function () {
$(".ticker1").click(function () {
if ($(this).is(":checked")) {
$(".subject1").prop("checked", true);
} else {
$(".subject1").prop("checked", false);
}
});
$(".ticker2").click(function () {
if ($(this).is(":checked")) {
$(".subject2").prop("checked", true);
} else {
$(".subject2").prop("checked", false);
}
});
});
</script>
Here I modified the code by changing ids to classes and made other necessary changes.

Select2: does not work once loaded through onclick event in vue js

We implemented the select2 on our select options in our project. In our project, we have item section(Inventory, Quantity and Unit) and in the bottom part there's a button "Add Item".
When I clicked the "Add Item", it will add new row in my item section. But the added row,my inventory doesn't have select2
EXAMPLE:
//
// As you can see here, this is the default when the user clicked the "Add" button
// When the user clicked the "Add Item"
As you can see, the select2 of my 2nd row in item didn't work but when I try again to add a new item. It will work.
Question: Why I have to add another row before my previous row in item to have a select2?
ADD vue
<button class="btn btn-primary" #click="addItem"><i class="fa fa-plus" aria-hidden="true"></i> Add Item</button>
Event
function getAssetLimit(){
var table = 'assets'
$('select.asset').select2({
placeholder: 'Select Asset',
allowClear: true,
ajax: {
url: '/select2/getAssetFilterLimit',
dataType: 'json',
data: function(params) {
return {
term: params.term || '',
page: params.page || 1,
table: params.table || table
}
},
cache: true
}
});
}
// export default
methods: {
addItem(e) {
e.preventDefault();
getAssetLimit();
// if (this.asset === 'undefined' || this.asset === '') {
this.inputs.push({
asset_id: '',
unit: '',
description: '',
});
},
Clicked the Add Item
<tbody>
<tr v-for="(input, i) in inputs" :key="i">
<td class="sticky">
<select class="form-control-input form-control asset" name="item_asset[]" :data-counter="i+1">
<option></option>
</select>
</td>
<td>
<input type="number" name="item_quantity[]" class="form-control form-control-input item-quantity" step="0.0001" required>
</td>
<td>
<input type="text" name="item_unit[]" class="form-control form-control-input item-unit" readonly="readonly" :data-counter="i+1">
</td>
<!-- <td v-if="asset[2]">
<textarea name="item_specification[]" class="form-control" readonly="readonly" :data-counter="i">{{ asset[2] | striphtml }}</textarea>
</td> -->
<!-- <td v-else> -->
<td>
<textarea name="item_description[]" class="form-control" readonly="readonly" :data-counter="i+1"></textarea>
</td>
</tr>
</tbody>

Set selected option selected inside a loop Vue.js

Im looping over a list of objects and I'm trying to have the status of the object be selected by default.
<template>
<table class="table is-striped">
<thead>
<tr>
<th>
Client
</th>
<th>
Status
</th>
</tr>
</thead>
<tbody>
<tr v-for="client in filteredClients">
<td>
<router-link :to="{ name:'client-show' , params:{clientId: client.uuid}}"
v-on:click.native="selectClient(client)">
{{ client.name }}
</router-link>
</td>
<td>
<div class="select is-rounded">
<select v-model="selectedStatus" #change="statusChange($event, client)">
<option v-for="status in statuses" > {{status}}</option>
</select>
</div>
</td>
</tr>
</tbody>
</table>
</template>
<script>
export default {
props: [
'filteredClients'
],
data: function() {
return {
statuses: [ 'Started', 'Awaiting Payment', 'Paid', 'Onboarding', 'Live']
}
},
computed: {},
mounted() {},
methods: {}
}
</script>
Here i have all the statuses that i need to display but im having a hard time getting a selected value to be selected for each object that im looping over through.
you need to $emit the status change to parent Component so that new status will be assigned to specific client object. (no mutation of props in child)
<select :value="client.status" #change="$emit('change', $event.target.value, client.uuid)">
<option v-for="status in statuses" :selected="status == client.status">{{status}}</option>
</select>
and on your parent Component, capture this emit and assign it to the client
<ParentComponent #change="(status, uuid) => clients.find(c => c.uuid === uuid).status = status">
// child with props: filteredClients
</ParentComponent>

AngularJS - nested ng-repeat with select/option, get/set the selected value

I am trying to set two ng-repeat loops, one of which, the nested one, is a select/option drop down. I checked other similar posts, but still not sure how to define the ng-model in HTML to get/set the default value/option in the select box.
<table>
<tr ng-repeat="student in studentList">
<td>{{student.name}}</td>
<td>
<select ng-model="courseSelected">
<option ng-repeat="course in courseList" value="{{course.id}}">{{course.name}}</option>
</select>
</td>
</tr>
</table>
Both studentList and courseList come from the database tables, and the student table/object has a courseId column/reference. In other words, the default selected course and the changed course option (if this happens) would have the logic behind them : student.courseId = course.id
Any help is appreciated.
<select ng-model="student.courseId" ng-options="course.name as course.id for course in courseList">
This should get you what you're looking for. I assumed that a course has the name property. But you can alias the course with any property you like in the ng-options directive. More documentation can be found here.
I think you should use ng-options in tag like:
<select ng-model="courseSelected" ng-options= "course.id for course in courseList">
maybe you should read these documentation for more explanation :
https://docs.angularjs.org/api/ng/directive/ngOptions
https://docs.angularjs.org/api/ng/directive/select
var editer = angular.module('app', []);
function myCtrl($scope) {
$scope.studentList = [{
id: 1,
name: 'Jack'
}, {
id: 2,
name: 'Terry'
}, {
id: 3,
name: 'Rosa'
}, {
id: 4,
name: 'Holt'
}];
$scope.courseList = [{
id: 1,
name: 'Course1'
}, {
id: 2,
name: 'Course2'
}];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl" class="container">
<table>
<tr ng-repeat="student in studentList">
<td>{{student.name}}</td>
<td>
<select ng-model="student.courseSelected" ng-options="course as course.name for course in courseList">
</select>
</td>
<td>
{{student.courseSelected.name}}
</td>
</tr>
</table>
<label class="item item-input">
<span class="input-label">Select date</span>
</label>
<pre>{{dateOption}}</pre>
</div>

How to get the value of a Select box implemented using ng-options which is inside a loop?

I have a list page displaying customer information and in each row of customers there is a Select box with some options like Edit, Cancel, Delete etc. The customers are displayed using ng-repeat directive and the select box with above mentioned options are implemented using ng-options.
I tried to get the value of selected item from drop down against each row, but it is not working, the code worked when I pasted the select box code snippet outside the loop.
Here is my code to display the customers
<table class="table display table-striped table-bordered" ng-table="tableParams">
<tr ng-repeat="customer in $data | filter: search | filter :name">
<td data-title="'Reseller ID'" sortable="'ResellerId'" >
{{customer.ResellerId}}
</td>
<td data-title="'Reseller Name'" sortable="'ResellerName'">
{{customer.ResellerName}}
</td>
<td data-title="'Customer ID'" sortable="'CustomerID'">
{{customer.CustomerID}}
</td>
<td data-title="'Customer Name'" sortable="'CustomerName'">
{{customer.CustomerName}}
</td>
<td data-title="'Status'" sortable="'Status'">
{{customer.Status}}
</td>
<td data-title="'Available Funds'" sortable="'AvailableFunds'">
{{customer.AvailableFunds}}
</td>
<td data-title="'Created Date'" sortable="'CreatedDate'">
{{customer.CreatedDate}}
</td>
<td>
<form name="statusForm">
<select class="form-control status" ng-model="actionslist" name="actions" ng-options="action.name for action in action_options" ng-change="editCustomer()">
<option value="">Select Action</option>
</select>
</form>
</td>
<td><i class="fa fa-desktop"></i> <i class="fa fa-rss"></i> <i class="fa fa-sign-in"></i> </td>
</tr>
</table>
Here is my Angular code
var CustomerController = function ($scope, $filter, $http, ngTableParams) {
$scope.action_options = [{
name: 'Edit',
value: 'edit'
}, {
name: 'Suspend',
value: 'suspend'
}, {
name: 'Cancel',
value: 'cancel'
}, {
name: 'Delete',
value: 'delete'
}, {
name: 'Reset Password',
value: 'reset'
}];
$scope.editCustomer = function () {
//$scope.itemList=[];
alert($scope.item.value);
//alert($scope.selected.actions);
}
}
Could anyone tell me what is the mistake I'm doing here ?
It will be saved through your ng-model
$scope.editCustomer = function () {
alert($scope.actionslist);
}
working fiddle
Try this:
<select ng-model="action" ng-options="obj.value as obj.name for obj in action_options"></select>
and check out this answer https://stackoverflow.com/a/12140310/1530725

Categories

Resources