Datatables in Bootstrap modal width - javascript

In my modal I am trying to put Datatables in there, the problem I'm having is that the width is incorrect, it should be the width of the modal but it is actually like this
My jQuery calling the Datatables
function getValidTags(){
var ruleID = $('.ruleID').val();
var table = $('.valid-tags').DataTable({
"ajax": {
"url": "/ajax/getValidTags.php",
"type": "POST",
"data": {
ruleID: ruleID
},
},
"columnDefs": [{
"targets": 2,
"render": function(data, type, full, meta){
return '<button class="btn btn-default btn-sm" type="button">Manage</button> <button class="btn btn-danger btn-sm">Delete</button>';
}
}]
});
}
My HTML
<!-- Modal where you will be able to add new rule -->
<div class="modal fade validation-list-modal" tabindex="-1" role="dialog" aria-labelledby="LargeModalLabel" aria-hidden="true" data-keyboard="false" data-backdrop="static">
<div class="modal-dialog modal-wide">
<div class="modal-content">
<div class="modal-header modal-header-custom">
<input class="ruleID" type="hidden"></input>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
<h4 class="modal-title modal-title-main">Create New Rule</h4>
</div>
<div class="modal-body">
<div class="topBar">
<div>
<input type="text" class="validTags inputTextStyling">
</div>
</div>
<table class="table table-striped table-condensed valid-tags">
<thead>
<tr>
<th>Tag Name</th>
<th>Autofixes</th>
<th>Manage</th>
</tr>
</thead>
<tbody class="validTagsTable">
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="saveValidTags">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>

I find this more appropriate solution,
First make your table width 100%
like this:
<table width="100%" id="datatable"></table>
then initialize your table
$('#datatable').DataTable();
and this this
$(document).on('shown.bs.modal', function (e) {
$.fn.dataTable.tables( {visible: true, api: true} ).columns.adjust();
});

For starters try adding following class to your table element
.dataTableLayout {
table-layout:fixed;
width:100%;
}
It would be good if you could make a fiddle of your code with dummy data for solving your problem.

I dont think the accepted answer is the correct answer. There should be no need at all for altering the CSS. It could cause unexpected issues elsewhere. The problem is, that the container (the modal) not is fully established at the time the dataTable is rendered. Look at columns.adjust() :
var table = $('#example').DataTable({
initComplete: function() {
this.api().columns.adjust()
}
...
})
or
$('.modal').on('shown.bs.modal', function() {
table.columns.adjust()
})

I just added table inside div, assigned width:100%; overflow-x:auto to that div and it worked.

Related

Datatable missing some rows when open in modal

In html I have a table defined inside a modal that opens when I click a button:
<button type="button" id="myBtn" class="btn btn-primary" onclick="createTable()">Open modal</button>
<div class="modal" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">myTable</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<table class="table table-striped table-bordered table-fixed" style="width:100%" id="myTable">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Date</th>
</tr>
</thead>
<tbody id="myTableBody"> </tbody>
</table>
</div>
</div>
</div>
</div>
I want to destroy and create the table each time I click the button, so I've defined this Javascript function to do that:
function createTable()
{
data = [{ID:'1', Name:'Name1', Date:'2022-04-27'}, {ID:'2', Name:'Name2', Date:'2022-04-27'}, {ID:'3', Name:'Name3', Date:'2022-04-27'}, {ID:'4', Name:'Name4', Date:'2022-04-27'} ]; // example of data
$("#myTable").find('tbody').empty(); // reset table
for (var i=0; i<data.length; i++) // fill rows
{
var row = `<tr>
<th scope="row"> ${data[i].ID}</th>
<td>${data[i].Name}</td>
<td>${data[i].Date}</td>
</tr>`
$("#myTable").find('tbody').append(row);
}
$("#myModal").modal("show"); // open modal
$('#myTable').DataTable({
scrollY: '400px',
scrollCollapse: true,
destroy: true
})
}
The problem is that, when I click the button, the modal opens but the table does not always contains all the data: sometimes the first rows (of data) are missing. If I refresh the page and then open the modal, all the rows are present.
data has size > 1000 and is taken from a DB, but in the code I only put an example of it. Here is the code https://jsfiddle.net/326w480u/
Any idea of the cause of this behavior?
EDIT1:
briefly, the problem is that Datatable is updated only when I refresh the page, not when I close and open the modal
EDIT2:
I solved populating the Datatable when I define it, and not by means of the for loop:
$('#myTable').DataTable({
scrollY: '400px',
data: data,
columns: [{data:'ID'},{data:'Name'},{data:'Date'}],
scrollCollapse: true,
destroy: true
})

datatable scrollX not working properly in dynamic column

I'm trying to display a lot of columns dynamically from geojson feature.properties in modal. I have successfully displayed it but the problem is when I click next page scrollX didn't work as intended.
Here is my code:
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document" style="margin:auto !important;max-width:1080px !important;">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Map Attributes</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="modalbody_1">
<div class="">
<table id="mapattr" class="display nowrap" style="width:100%" cellspacing="0">
<thead></thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script>
var dataGSet = [];
var dataGArray;
var columnRef = [];
$.get(url, function(data) {
columnRef = [];
$("#mapattr > thead").append("<tr></tr>");
$.each(data.features, function(a, b) {
var cRow = [];
$.each(b.properties, function(key, value) {
if (a == 0) {
$("#mapattr > thead > tr").append("<td>" + key + "</td>");
columnRef.push({
title: key
})
}
cRow.push(value);
});
dataGSet.push(cRow);
});
}).done(function() {
dataGArray = JSON.parse(JSON.stringify(dataGSet));
if (!$.fn.DataTable.isDataTable('#mapattr')) {
$("#mapattr").DataTable({
dom: 'Bfrtip',
data: dataGArray,
scrollX: true,
buttons: [
'copy', 'csv', 'excel', 'pdf'
]
});
} else {
$('#mapattr').DataTable().destroy();
$('#mapattr').empty();
$("#mapattr").DataTable({
dom: 'Bfrtip',
data: dataGArray,
scrollX: true,
buttons: [
'copy', 'csv', 'excel', 'pdf'
]
});
}
});
</script>
First load:
When I click page 2:
I already tried the table-responsive suggestion from this article but the problem with the user scrolling it, the buttons, page, and search box will also be scrolled so it's a little hassle for the client when they want to navigate in another page.

Send an event to another function

Problem
Is there a way to send 'event' to another function with jQuery?
I have this code to prevent remove of row of my table to execute certain treatments, then remove the row.
I want to add a modal window between. But I do not know how to proceed.
Actually, I do like this
$('#delete-row').on('click', '.tr-special .remove-line-exceptionnel', function (event) {
event.preventDefault();
var $row = $(event.target).closest('.tr-special');
console.log($row);
var elementSortable = $row.find('ul').attr('id');
items = $row.find('li');
$( items ).each(function( index ) {
//function out of purpose
});
$row.remove();
});
Output of console.log is
r.fn.init [tr.tr-special, prevObject: r.fn.init(1)]
I want to call my modal, after click on Delete button with class .remove-line, so in normal times I do like this
$('.remove-line').on('click', function (event) {
$('#custom-width-modal').modal('show');
});
And what I would like is : when I press the button Confirm in my modal, the code of $('#delete-row').on('click', '.tr-special .remove-line', function (event) {.. execute.
$('.modal-footer').on('click', '.validDelete', function(e) {
var $row = $(e.target).closest('.tr-special');
console.log($row);
});
Output of console.log is
r.fn.init [prevObject: r.fn.init(1)]
I hope you understand me
If you simply declare the $row variable globally...
In the .remove-line-exceptionnel click handler, store the element to possibly delete. Then in the .validDelete click handler, you remove the element.
So there is no send an event anywhere. There is two events... One to know which element to delete and one to actually do it.
// Declare a variable globally
var $row;
// Button (or whatever) in the row
$('#delete-row').on('click', '.tr-special .remove-line-exceptionnel', function (event) {
// Store the row element to delete
$row = $(event.target).closest('.tr-special');
// Show modal
$('#custom-width-modal').modal('show');
});
// Modal button
$('.modal-footer').on('click', '.validDelete', function(e) {
// Remove the row
$row.remove();
// Hide modal
$('#custom-width-modal').modal('hide');
});
table{
margin: 0 auto;
}
td{
padding: 1em;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<table id="delete-row">
<tr class="tr-special">
<td>Row 1</td>
<td><button class="remove-line-exceptionnel">Remove</button></td>
</tr>
<tr class="tr-special">
<td>Row 2</td>
<td><button class="remove-line-exceptionnel">Remove</button></td>
</tr>
<tr class="tr-special">
<td>Row 3</td>
<td><button class="remove-line-exceptionnel">Remove</button></td>
</tr>
</table>
<div id="custom-width-modal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary validDelete">Yes, I'm sure.</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>

How to load dynamic content in bootstrap modal

i have create a bootstrap modal but i need the content to be dynamic. Each time i select a different table row, the content of that row should popup. The content inside bootstrap modal is a dynamic table. Is possible to show a simple sample of how by selecting from the row of a table, i can get a dynamic table in the popup modal. Please help. Thanks
while($row = $results->fetch_assoc()): ?>
<tr>
<td class="list-answer"
data-toggle="modal"
href="#content-confirmation">
<?= $row["name"]; ?>
</td>
</tr>
<?php endwhile ?>
<div class="control-popup modal fade" id="content-confirmation"
tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal"
aria-hidden="true">×</button>
<h4 class="modal-title">Are you sure you wanna do
that?</h4>
</div>
<div class="modal-body">
load dynamic table content.......
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default"
data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary"
data-dismiss="modal">Save</button>
</div>
</div>
</div>
Are you trying to give your table column a link with href ? because it would not work like that.
To your question, there are multiple ways of doing this. I would give the table's row an id and handle the row click or column click event in js code. after that i would get that rows content either with an ajax request or directly from the table's columns.
So your code would look like:
while($row = $results->fetch_assoc()): ?>
<tr data-id="<?= $row["id"]; ?>">
<td class="list-answer">
<?= $row["name"]; ?>
</td>
</tr>
your javascript code:
$(function(){
$(".list-answer").click(function() {
var row_id = $(this).parents('tr').attr('data-id');
get_data(row_id);
$('#my-modal').modal();
});
});
function get_data(row_id) {
//either get data with ajax request or row
//fill modals content with $('#input-field-id').val('vlaue') or .html()
}
$.ajax({
url : 'url',
method : 'post',
data: {
},
success : function(response)
{
$('#my-modal').html(response);
// put your html response in the popup div
$('#my-modal').modal();
}
});
<div id="my-modal"></div>
I don't know if i understand well, but i think you need something like me :
$("table").on('click', 'tr', function() {
var json_data = {
"controller": "NameOfController",
"action": "action",
"contentofRow": $(this).text()
};
$.post('ajax_handler.php', json_data, function (res) {
if (res.indexOf('ERREUR') != -1) {
alert(res);
return false;
}
else {
$('#mymodalID').modal();
$("#myModalLabel").html("Content of the row : " + res[0]);
$.each(res[1], function (index, valeur) {
$("#bodySupp").append($('<tr>')
.css("text-align", "center")
.css("fontSize", "12px")
.append($('<th>')
.html(valeur['indexOfValue'])
)
.append($('<th>')
.html(index)
)
.append($('<th>')
.html(valeur['indexOfValue2'])
)
.append($('<th>')
.html(valeur['indexOfValue3'])
)
)
});
}
}, 'json');
});
$("table").on('click', 'tr', function()
You open the modal on the click on the row of the table,
"contentofRow": $(this).text()
You take the content of the current row, this is what you will display :)
And then you have the controller :
class NameOfController implements AjaxControler {
public function execute($data)
{
switch($data['action']){
default :
$contentRow= $data['yourcontent'];
$res = array();
$res[] = $contentRow
return json_encode($res);
}
}
}
You can do that in OctoberCMS backend. I'll give you a quick example.
I put that in a controller _list_toolbar.htm
<button
href="javascript:;"
data-control="popup"
data-size="large"
disabled="disabled"
data-trigger-action="enable"
data-trigger=".control-list input[type=checkbox]"
data-trigger-condition="checked"
onClick="$(this).popup({ handler: 'onAssignTechnical', extraData: { checked: $('.control-list').listWidget('getChecked') } })"
href="javascript:;"
class="btn btn-default oc-icon-plus">
<?= e(trans('lilessam.maintenancesystem::lang.work_orders.assigntechnical_button')) ?>
</button>
And in the onAssignTechnical() in the controller I'll make a bootstrap modal.
public function onAssignTechnical() {
/** Check if this is even set **/
if (($checkedIds = post('checked')) && is_array($checkedIds) && count($checkedIds)) {
foreach($checkedIds as $workorder_checked_id) {
$check_work_order = \Lilessam\Maintenancesystem\Models\WorkOrder::where(['id' => $workorder_checked_id, 'assigned_to_id' => null])->count();
}
/** Check if there's more than one record checked */
if(count($checkedIds) == 1 && $check_work_order != 0):
/**Labels **/
$modal_title = Lang::get('lilessam.maintenancesystem::lang.assign_technical_title');
$assign_label = Lang::get('lilessam.maintenancesystem::lang.assign_label');
$name_label = Lang::get('lilessam.maintenancesystem::lang.assign_modal_name_label');
$action_label = Lang::get('lilessam.maintenancesystem::lang.assign_modal_action_label');
/** Getting all workers IDS by their group id 2 **/
$allWorkers_ids = DB::table('backend_users_groups')->where('user_group_id', 2)->get();
/** Workers Array **/
$workers_array = [];
// Looping to get all workers
foreach($allWorkers_ids as $worker_id) {
//Fetching the user
$worker = User::find($worker_id->user_id);
//Pushing the worker to workers' array
array_push($workers_array, [
'login' => $worker->login,
'first_name' => $worker->first_name,
'last_name' => $worker->last_name,
'id' => $worker->id,
]);
}
#setting the table header
$workers_code = '<div class="control-list list-unresponsive">
<table class="table data" data-control="rowlink">
<thead>
<tr>
<th>'.$name_label.'</th>
<th style="width: 150px"><span>'.$action_label.'</span></th>
</tr>
</thead>
<tbody>';
#Adding workers to the table
foreach($workers_array as $worker_row) {
foreach($checkedIds as $workorder_id):
$workers_code .= '<tr>
<td>
<a href="javascript:;">
'.$worker_row['first_name']." ".$worker_row['last_name'].'
</a>
</td>
<td>
<form method="post" data-request="onAssignNow">
<input type="hidden" name="workorder_id" value="'.$workorder_id.'">
<input type="hidden" name="id" value="'.$worker_row['id'].'">
<button type="submit" class="btn btn-info">'.$assign_label.'</button>
</form>
</td>
</tr>';
endforeach;
}
#Adding Table Fotter
$workers_code .= "</tbody>
</table>
</div>";
#Returning all modal
return '
<div class="control-popup modal fade in" id="content-confirmation" tabindex="-1" role="dialog" aria-hidden="false" style="display: block;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">'.$modal_title.'</h4>
</div>
<div class="modal-body">
<div class="form-group textarea-field span-full" data-field-name="idea" id="Form-field-Idea-idea-groupc" style="height: 395px;
overflow-x: hidden;
margin-bottom: 20px;
overflow-y: scroll;">
<div class="qa-message-list" id="wallmessages">
'.$workers_code.'
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">X</button>
</div>
</div>
</div>
</div>
';
else:
/** Labels **/
$warning_title = Lang::get('lilessam.maintenancesystem::lang.assign_technical_warning_title');
$warning_body = Lang::get('lilessam.maintenancesystem::lang.assign_technical_warning');
#Returning all modal
return '
<div class="control-popup modal fade in" id="content-confirmation" tabindex="-1" role="dialog" aria-hidden="false" style="display: block;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">'.$warning_title.'</h4>
</div>
<div class="modal-body">
<div class="form-group textarea-field span-full" data-field-name="idea" id="Form-field-Idea-idea-groupc" style="height: 395px;
overflow-x: hidden;
margin-bottom: 20px;
overflow-y: scroll;">
<div class="qa-message-list" id="wallmessages">
'.$warning_body.'
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">&#10006</button>
</div>
</div>
</div>
</div>
';
endif;
}
}
Excuse me for the long code but I'm sure It will help you.

Uncaught Error: You cannot apply bindings multiple times to the same element

How could I combine the two models which i have kept for two different purpose. One is to for file upload and the other is for render data from different object.Below is the respective html and JS i tried.
HTML section
<div class="well" data-bind="fileDrag: fileData">
<div class="form-group row">
<div class="col-md-6">
<img style="height: 125px;" class="img-rounded thumb" data-bind="attr: { src: fileData().dataURL }, visible: fileData().dataURL">
<div data-bind="ifnot: fileData().dataURL">
<label class="drag-label">Drag file here</label>
</div>
</div>
<div class="col-md-6">
<input type="file" data-bind="fileInput: fileData, customFileInput: {
buttonClass: 'btn btn-success',
fileNameClass: 'disabled form-control',
onClear: onClear,
}" accept="application/pdf,image/*">
</div>
</div>
</div>
<button class="btn btn-default" data-bind="click: debug">Upload</button>
</div>
<div id="notification" style="display: none;">
<span class="dismiss"><a title="dismiss this notification">X</a></span>
</div>
<!-- Collapsible Panels - START -->
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Plan Details</h3>
</div>
<div class="panel-body">
<span class="glyphicon glyphicon-plus clickable" id="addPlanBtn"></span>
<span class="glyphicon glyphicon-remove clickable" id="removePlanBtn"></span>
<span class="glyphicon glyphicon-edit clickable" id="editPlanBtn"></span>
<table id="docsDataTable" class="table table-striped display" width="100%">
<thead>
<tr>
<th></th>
<th>Contract Document ID</th>
<th>Contract ID</th>
<th>Document Name</th>
<th>File Path</th>
<th>Comments</th>
</tr>
</thead>
</table>
<div class="modal fade" id="notificationDialog" role="dialog">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" \>×</button>
<h4 class="modal-title">Notification</h4>
</div>
<div class="modal-body" id="notificationBody">
</div>
<div class = "modal-footer">
<button type = "button" class = "btn btn-primary" data-dismiss = "modal">
Ok
</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="confirmBox" role="dialog">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" \>×</button>
<h4 class="modal-title">Confirmation</h4>
</div>
<div class="modal-body" id="confirmBody">
Selected rows will be made inactive.
</div>
<div class = "modal-footer">
<button type = "button" class = "btn btn-default" data-dismiss = "modal" id="confirmNoBtn">
Cancel
</button>
<button type = "button" class = "btn btn-primary" data-dismiss = "modal" id="confirmYesBtn">
Ok
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Javascript section to bind the data
var dataset;
var docsModel;
var docsTable;
var vasTypes;
$(function(){
var viewModel = {};
viewModel.fileData = ko.observable({
dataURL: ko.observable(),
// base64String: ko.observable(),
});
viewModel.onClear = function(fileData){
if(confirm('Are you sure?')){
fileData.clear && fileData.clear();
}
};
viewModel.debug = function(){
window.viewModel = viewModel;
//console.log(ko.toJSON(viewModel));
fileUpload(viewModel);
debugger;
};
ko.applyBindings(viewModel);
});
$(document).ready(function(){
docsModel = new $.cordys.model({
context: document.getElementById("addPanelForm"),
objectName: "CONTRACT_DOCUMENT",
fields: ["CONTRACT_DOCUMENT_ID" , "CONTRACT_ID" , "DOCUMENT_NAME" , "FILE_PATH" , "COMMENTS"],
defaults: {
namespace: "http://services.vw.com/lpms/1.0/wsapp"
},/*
update: {
method: "UpdatePlanVas"
},*/
read: {
method: "GetContractDocumentObjectsForContractId",
parameters: {
CONTRACT_ID: "CONTRACT_1000"
},
}
});
GetContractDocumentObjectsForContractId();
docsTable = $('#docsDataTable').DataTable({
data: dataset,
columnDefs: [ {
orderable: false,
className: 'select-checkbox',
defaultContent: "",
targets: 0},
{ data: "CONTRACT_DOCUMENT_ID",
targets: 1,
visible: false},
{ data: "CONTRACT_ID",
targets: 2},
{ data: "DOCUMENT_NAME",
targets: 3},
{ data: "COMMENTS",
targets: 5},
{ data: "FILE_PATH",
targets: 4}],
select: {
style: 'multi',
selector: 'td:first-child'
},
order: [[ 1, 'asc' ]],
"searching": false,
"lengthChange": false
});
});
function fileUpload(data){
dataObject=ko.toJS(viewModel);
fileName=dataObject.fileData.file.name;
fileContent=dataObject.fileData.dataURL.split(',')[1];
$.cordys.ajax({
method: "WriteFile",
parameters: {
filename: fileName,
encoded: "true",
data:fileContent
},
namespace:"http://schemas.cordys.com/1.0/ac/FileConnector",
dataType: "* json",
async: false,
success: function(e){
$.notify("Yeah ! File Uploaded", "success");
}
});
}
You're getting the error
You cannot apply bindings multiple times to the same element
Because Knockout only permits one view-model to be bound to a DOM element.
In your case, you need to somehow combine the two view-models into one. While you could simply add the properties from one view-model into the other, perhaps creating a third view-model with a new name so you can continue using the original form of these view-models elsewhere, my suggestion would be to create a new super view-model, and reference the two existing view-models as properties on this new view-model.
At this point I would normally create an example from the code in the OP but in this case, as #Jeroen has pointed out, it's rather difficult to make out what's going on in the OP. As far as I can see, there's only one view-model in there while your question revolves around having two view-models. So the following example is unfortunately very generic.
var ViewModel1 = function() {
var self = this;
self.obs1_1 = ko.observable();
self.obs1_2 = ko.observableArray([]);
// some initialisation stuff
},
ViewModel2 = function() {
var self = this;
self.obs2_1 = ko.observable();
self.obs2_2 = ko.observableArray([]);
// some initialisation stuff
},
SuperViewModel = function() {
var self = this;
self.vm1 = new ViewModel1();
self.vm2 = new ViewModel2();
// some initialisation stuff
};
You would then instantiate and data-bind SuperViewModel, and reference the observables like so
<input type="text" data-bind="textInput: vm1.obs1_1" />
<div data-bind="foreach: vm1.obs1_2">
<span data-bind="html: $data"></span>
</div>
or to make typing a little bit easier
<!-- ko with: vm1 -->
<input type="text" data-bind="textInput: obs1_1" /> <!-- this time without "vm1." -->
<div data-bind="foreach: obs1_2"> <!-- this time without "vm1." -->
<span data-bind="html: $data"></span>
</div>
<!-- /ko -->
You now have a single view-model, SuperViewModel, referencing your unchanged existing view-models. This solution allows you to leave existing JavaScript and views while offering an easy method of data-binding the functionality of multiple view-models inside a single view-model.
It's technically possible to achieve a similar result by doing some referencing at the prototype level, but that could quickly cause complications and the only advantage would be saving you from typing the name of a property.

Categories

Resources