How to pass variables to SuiteQL - suitescript

I am trying to pass parameters from the current record to an embedded Suitelet though cannot find the right syntax to do this anywhere
My starting point was using the Suitelet code here: https://timdietrich.me/blog/netsuite-suiteql-query-results-custom-tabs/
The result from my modified version is per this screencap
When the page loads, the SuiteQL record field is populated using the current record's internal Id.
What I want to do is pass this value as a variable to the embedded SuiteQL Suitelet so that the search results are only in relation to the stated record (in this case, the record with the internal id=24486).
Is this actually possible?
If it is possible, how do I pass this value to the SQL query parameters?
This is the full modified version of the code:
/**
* #NApiVersion 2.1
* #NScriptType UserEventScript
* #NModuleScope Public
*/
/*
*/
var log, query, serverWidget;
define([
"N/log",
"N/query",
"N/ui/serverWidget",
"N/record",
"N/runtime",
"N/recordContext",
], main);
function main(
logModule,
queryModule,
serverWidgetModule,
recordModule,
runtimeModule,
recordContextModule
) {
log = logModule;
query = queryModule;
serverWidget = serverWidgetModule;
record = recordModule;
runtime = runtimeModule;
recordContext = recordContextModule;
return {
beforeLoad: beforeLoad,
};
}
function beforeLoad(context) {
if (context.type !== context.UserEventType.VIEW) {
return;
}
var suiteqlTab = context.form.addTab({
id: "custpage_sql_tab",
label: "SuiteQL Tab",
});
context.form.insertTab({
tab: suiteqlTab,
nexttab: "items",
});
var recordId = runtime.getCurrentScript();
log.debug({
title: "recordId",
details: recordId,
});
var parms = context.request.parameters;
log.debug("params", parms);
log.debug("recordid", parms.id);
var id = parms.id;
var recordField = context.form.addField({
id: "custpage_suiteql_record",
type: serverWidget.FieldType.TEXT,
label: "SuiteQL Record",
container: "custpage_sql_tab",
});
recordField.defaultValue = id;
var suiteqlField = context.form.addField({
id: "custpage_suiteql_field",
type: serverWidget.FieldType.TEXT,
label: "SuiteQL Query Results",
container: "custpage_sql_tab",
});
var records = sqlQueryRun();
context.newRecord.setValue({
fieldId: "custpage_suiteql_field",
value: sqlResultsTableGenerate(records),
});
}
function sqlQueryRun() {
var sql = `
SELECT
Transaction.type
FROM
Transaction
Where Transaction.type like 'SalesOrd'
`;
return query.runSuiteQL({ query: sql, params: [] }).asMappedResults();
}
function sqlResultsTableGenerate(records) {
if (records.length === 0) {
return "<div><p>No records were found.</p></div>";
}
let thead = `
<thead>
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>Email</th>
<th>Phone #</th>
</tr>
</thead>`;
var tbody = "<tbody>";
for (r = 0; r < records.length; r++) {
var record = records[r];
tbody += `
<tr>
<td></td>
<td></td>
<td>${record.email}</td>
<td>${record.phone || ""}</td>
</tr>`;
}
tbody += "</tbody>";
let stylesheet = `
<style type = "text/css">
/* Styled Table */
/* https://dev.to/dcodeyt/creating-beautiful-html-tables-with-css-428l */
.styled-table {
border-collapse: collapse;
margin: 25px 0;
font-size: 0.9em;
font-family: sans-serif;
min-width: 400px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
width: 100%;
}
.styled-table th,
.styled-table td {
padding: 6px;
}
.styled-table thead tr {
background-color: #607799;
color: #ffffff;
text-align: left;
}
.styled-table tbody tr {
border-bottom: thin solid #dddddd;
}
.styled-table tbody tr:nth-of-type(even) {
background-color: #f3f3f3;
}
.styled-table tbody tr.active-row {
font-weight: bold;
color: #009879;
}
.styled-table tbody tr:hover {
background-color: #ffff99;
}
</style>
`;
return `
${stylesheet}
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.25/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.js"></script>
<div style="margin-top: 6px; border: 1px solid #ccc; padding: 24px;">
<table id="sqlResultsTable" class="styled-table" style="width: 100%;">
${thead}
${tbody}
</table>
</div>
<script>
window.jQuery = window.$ = jQuery;
$('#sqlResultsTable').DataTable( { "pageLength": 10, "lengthMenu": [ 10, 25, 50, 75, 100 ] } );
</script>
`;
}
The original author of the SuiteQL tool: Timothy Dietrich

Related

Image size does not change when I configured as responsive design

What I want to do
I created the homepage that has some images. I would like to show up them by the responsive design. However, all image files' size are not changed when I show on the iPhone.
There are 3 types img files on HP.
The images are ...
files shows up by changing the 3 pics by each 2 seconds at the same place.
normal img files.
As the gallery, that the img file change to show up by clicking the thumbnail button.
All of them are not changed img size when responsive.
//const img = ["hoge.png", "foo.png", "bar.jpg"];
const img = ["https://lh3.googleusercontent.com/taykG37GWDgY-FGkdogDvsHSJMUGRMvkuVRT6yR-5UNkKvGRKeRlpGYXlslocOcS0txlfUdGW59JGtzADknxbMqnh6AtVCv9EXyB8nHp80YsRNA0Yw=w1024-h683-n-l50-sg-rj", "https://lh3.googleusercontent.com/fl-GT6w3Ls6RT4vYnbkuYUyLY3lZJH8VtZ7xzxiym9YYaoVRCnZehdz6Icd0oAf6i3H9-O5cCNs6eunlxWr_Csstgsb98DdzNdLFBOlhw9NUfHdyuQjI=w768-h1024-n-l50-sg-rj", "https://lh3.googleusercontent.com/9pPCK70Rw0k3wethMHb1qMaIB0VjeWLy57vYgSzKbF7oJuvO2nA0Nakk-95cvibWUDcEhYkfCKvdPKT03tXZd4M5jdhIEibLO9qw-XE=w1024-h683-n-l50-sg-rj"];
let count = -1;
const hoge = () => {
count++;
// カウントが最大になれば初期値に戻す
if (count == img.length) count = 0;
//画像選択
pic.src = img[count];
//1秒ごとに実行
setTimeout(() => {
hoge();
}, 2000);
}
window.onload = () => {
hoge();
}
//アルバムデータの作成
let album = [{
src: 'img/1.png',
msg: 'さまざまな形のパスタと自然の恵みを生かしたイタリアン'
},
{
src: 'img/2.png',
msg: 'パスタだけでなく軽食やスイーツも'
},
{
src: 'img/3.png',
msg: '肉料理やピザもイタリアン料理を彩ります'
},
{
src: 'img/4.png',
msg: '豊富な種類のピザ'
},
{
src: 'img/5.png',
msg: 'チーズが主役だったり生ハムが主役だったり、ピザの種類は豊富です'
}
];
//最初のデータを表示しておく
let mainImage = document.createElement('img');
mainImage.setAttribute('src', album[0].src);
mainImage.setAttribute('alt', album[0].msg);
let mainMsg = document.createElement('p');
mainMsg.innerText = mainImage.alt;
let mainFlame = document.querySelector('#gallery .main');
mainFlame.insertBefore(mainImage, null);
mainFlame.insertBefore(mainMsg, null);
//サムネイル写真の表示
let thumbFlame = document.querySelector('#gallery .thumb');
for (let i = 0; i < album.length; i++) {
let thumbImage = document.createElement('img');
thumbImage.setAttribute('src', album[i].src);
thumbImage.setAttribute('alt', album[i].msg);
thumbFlame.insertBefore(thumbImage, null);
}
//クリックした画像をメインにする
thumbFlame.addEventListener('click', function(event) {
if (event.target.src) {
mainImage.src = event.target.src;
mainMsg.innerText = event.target.alt;
}
});
.under {
border-bottom: dotted 2px #87cdfa
}
.fixed {
width: 300px;
height: auto;
}
img.calbo {
width: 100%;
height: auto;
}
img.pepe {
width: 100%;
height: auto;
}
#gallery {
margin: 0;
padding-top: 40px;
width: 700px;
}
#gallery .main img {
border: 4px solid #fff;
box-shadow: 0;
}
#gallery .main p {
color: #bbb;
font-size: 20px;
font-weight: bold;
}
#gallery .thumb img {
border: 4px solid #fff;
border-radius: 400px;
box-shadow: 0px 0px 10px #000;
height: 60px;
margin: 10px;
width: 60px;
cursor: pointer;
}
#media screen and (max-width: 480px) {
test {
float: none;
}
img {
width: 100%;
}
}
<h1>
<font color="#EEEEEE">レシピ ~ カルボナーラとペペロンチーノ</h1>
<br>
<hr width="700" align="left">
<!--- html ----->
<img id="pic" src="hoge.png" width="600" height=auto class="top">
<p>
<table>
<tr>
<th class="fixed"><img src="calbo150.png" class="calbo"></th>
<td style="background-color:#476072">
ちょっとしたひと工夫で普通の手作り<br> カルボからお店風本格カルボに。
<br> 失敗もしない簡単レシピ
<br><br>
カルボナーラのレシピ
</td>
</tr>
<tr>
<th class="fixed"><img src="pepe.jpg" class="pepe"></th>
<td style="background-color:#476072">
簡単だけど難しいペペロンチーノ。<br> 材料と水分調整がうまくいけば本格的な
<br> ペペロンチーノに仕上がります。
<br><br>
ペペロンチーノのレシピ
</td>
</tr>
</table>
</p>
<!-- JavaScript -->
<div id="gallery">
<div class="main">
</div>
<div class="thumb">
</div>
</div>
Although I didn’t paste the full HTML here, I used the double byte double quotation in the settings of the Viewport line. After I modified to single byte one, it started to work.

How to display correctly my DataTables table?

I have created a Datatables table using AJAX, but when I try to render it, the <tr> inside the <tbody>, are shorter than those in the <thead>.
There are 2 pages: the first one is the form and the header of the table, hidden by default. When the user clicks on the search button, it displays the header and loads the table body via AJAX. The result is the following:
style.css
.outcomeResearchTable {
z-index: 100;
background-color: white;
display: none;
}
.outcomeResearchTable th {
/*padding:1.0rem; */
width: 100px !important;
/* border-bottom:1px solid lightgray; */
background-color: #FFFFFF;
}
.outcomeResearchTable th:first-of-type {
padding: 1rem;
width: 80px !important;
}
.outcomeResearchTable th:last-of-type {
padding: 1rem;
width: 80px !important;
}
#OUTCOME_RESEARCH_TABLE thead {
display: none;
}
.outcomeResearchTable td {
padding: 1rem;
width: 100px;
}
.outcomeResearchTable td:first-of-type {
padding: 1rem;
width: 80px !important;
}
.outcomeResearchTable td:last-of-type {
padding: 1rem;
width: 80px !important;
}
page1.php
<td colspan="2">
<button class="btn btn-primary" onclick="assetSearch();" tabindex="4">Ricerca</button>
<?php
echo "<table id=\"OUTCOME_RESEARCH_TABLE\" class=\"display outcomeResearchTable\" cellspacing=\"0\" width=\"100%\">\n";
echo "<thead>\n";
echo "<tr>\n";
echo "<th>IDConfig</th>\n";
echo "<th>Nome</th>\n";
echo "<th>Tipo</th>\n";
echo "<th>Stato</th>\n";
echo "<th>Ambiente</th>\n";
echo "<th>Aggregatore</th>\n";
echo "<th>Locazione</th>\n";
echo "<th>Modello</th>\n";
echo "<th>Contratto</th>\n";
echo "<th>Valida Dal</th>\n";
echo "<th>Valida Al</th>\n";
echo "<th>Dettagli</th>\n";
echo "</tr>\n";
echo "</thead>\n";
echo "</table><br />\n";
?>
</td>
assePageScript.js
function assetSearch() {
var validation = checkForSelectedFields();
if (validation == "KO") {
return;
}
var arrForm = [];
arrForm.push(document.getElementById("name").value); // 0
//arrForm.push(document.getElementById("idConfig").value);
arrForm.push(document.getElementById("serialNumber").value); // 1
arrForm.push(document.getElementById("tipo").value); // 2
arrForm.push(document.getElementById("ambiente").value); // 3
arrForm.push(document.getElementById("modello").value); // 4
arrForm.push(document.getElementById("locazione").value); // 5
arrForm.push(document.getElementById("vendor").value); // 6
arrForm.push(document.getElementById("gruppo").value); // 7
arrForm.push(document.getElementById("stato").value); // 8
arrForm.push(document.getElementById("classe").value); // 9
arrForm.push(document.getElementById("securityLevel").value); // 10
arrForm.push(document.getElementById("aggregatore").value); // 11
$.ajax({
url: "asset_GestAsset.php",
type: "POST",
data: {
"fieldValue": JSON.stringify(arrForm)
},
success: function(data) {
var outcomeResearchTable = document.getElementById("OUTCOME_RESEARCH_TABLE");
outcomeResearchTable.style.display = "flex";
var outComeRT = $('#OUTCOME_RESEARCH_TABLE').DataTable({
paging: true,
"bAutoWidth": false,
"dom": 'ltipr',
"data": data,
"destroy": true,
"pageLength": 100,
"scrollY": 400,
"scrollX": true,
"ordering": true
});
},
error: function(err) {
alert("Errore " + err);
}
});
}

Change td style based on value in angular

I have a column where the style of each td needs to be changed based on value. There are five status's, so there has to be five different border-colors and font-colors. How do I do this in angular script without hard-coding (new to angular)?
What I am doing is:
In html:
<table st-table = "tenants" class="table table-striped table-bordered">
<tbody>
<tr dir-paginate="t in tenants | orderBy:sortColumn:reverseSort | filter:searchText | itemsPerPage:itemsPerPage" current-page="currentPage" >
<td ng-if="t.status.color==2"><b class = 'td_status'>{{t.status.id}}<b></td>
In css:
.td_status {
border-radius: 20px;
width: auto;
height: auto;
min-width: 100px;
display: inline-block;
text-align: center;
border: 1px solid red;
padding: 5px;
}
In js:
datax.forEach(function(obj,i){
if (obj.last_paid) {
if (obj.stripe_status == "active") {
obj.status = {
'id' : "Paid: Last Paid " + $filter('date')(obj.last_paid, 'MM-dd-yyyy'),
'value': "Paid: Last Paid " + $filter('date')(obj.last_paid, 'yyyy-MM-dd HH:mm:ss Z'),
'color' : 0
}
}
else if (obj.stripe_status == "past_due" || obj.stripe_status == "unpaid") {
obj.status = {
'id' : "Past Due: Last Paid " + $filter('date')(obj.last_paid, 'MM-dd-yyyy'),
'value': "Past Due: Last Paid " + $filter('date')(obj.last_paid, 'yyyy-MM-dd HH:mm:ss Z'),
'color' : 4,
}
}....
I made an example since it is a little slow at work.
Here you can see my use of ng-class. I give it a function and pass the status which is defined in $scope.data item.status comes from my ng-repeat
<div ng-app="TestApp" ng-controller="TestController">
<p ng-repeat="item in data" ng-class="getBorderColor(item.status)">
{{item.name}}
</p>
</div>
Below I have my controller and some sample data. The getBorderColor runs through its conditions and returns className based off of status.
var app = angular.module('TestApp', []);
app.controller('TestController', function($scope) {
$scope.data = [
{
name:'Ronnie',
status:1
},
{
name:'Chance',
status:2
},
{
name:'Mike',
status:1
},
{
name:'Mark',
status:3
}];
$scope.getBorderColor = function(status) {
var className = '';
if (status == 1) {
className = 'status1';
} else if (status == 2) {
className = 'status2';
} else if (status == 3) {
className = 'status3';
}
return className;
};
});
And my simple css is:
.status1 {
border:1px solid red;
}
.status2 {
border:1px solid blue;
}
.status3 {
border:1px solid green;
}
https://jsfiddle.net/ojzdxpt1/7/

Turn cell content to editable input box

When creating a fluid layout, where content can be dragged around and edited inside a table I ran into a problem.
After clicking on any of the <a></a> hyperlinks the cell content should be replaced by an editable input box.
This gets done, but the cell changes its size and wrecks the original layout.
The cell size should not change after click. It should be possible to achieve this by editing the CSS and adding Bootstrap classes.
var viewModel = function() {
var self = this;
self.gridItems = ko.observableArray(
[{
"rowItems": [{
"name": "Item 1"
}, {
"name": "Item 2"
}, {
"name": "Item 3"
}]
}, {
"rowItems": [{
"name": "Item 4"
}, {
"name": "Item 5"
}]
}]
);
self.selectedRowItem = ko.observable();
};
//connect items with observableArrays
ko.bindingHandlers.sortableList = {
init: function(element, valueAccessor, allBindingsAccessor, context) {
$(element).data("sortList", valueAccessor()); //attach meta-data
$(element).sortable({
update: function(event, ui) {
var item = ui.item.data("sortItem");
if (item) {
//identify parents
var originalParent = ui.item.data("parentList");
var newParent = ui.item.parent().data("sortList");
//figure out its new position
var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);
if (position >= 0) {
originalParent.remove(item);
newParent.splice(position, 0, item);
}
ui.item.remove();
}
},
connectWith: '.sortable-container'
});
}
};
//attach meta-data
ko.bindingHandlers.sortableItem = {
init: function(element, valueAccessor) {
var options = valueAccessor();
$(element).data("sortItem", options.item);
$(element).data("parentList", options.parentList);
}
};
//control visibility, give element focus, and select the contents (in order)
ko.bindingHandlers.visibleAndSelect = {
update: function(element, valueAccessor) {
ko.bindingHandlers.visible.update(element, valueAccessor);
if (valueAccessor()) {
setTimeout(function() {
$(element).focus().select();
}, 0); //new RowItems are not in DOM yet
}
}
}
ko.applyBindings(new viewModel());
//$(".sortable").sortable({});
.sortable {
list-style-type: none;
margin: 0;
padding: 0;
width:100%;
}
.sortable li {
margin: 0 3px 3px 3px;
padding: 0.4em;
padding-left: 1.5em;
font-size: 1.4em;
height: 18px;
cursor: move;
}
.sortable li span {
position: absolute;
margin-left: -1.3em;
}
.sortable li.fixed {
cursor: default;
color: #959595;
opacity: 0.5;
}
.sortable-grid {
width: 100% !important;
}
.sortable-row {
height: 100% !important;
padding: 0 !important;
margin: 0 !important;
display: block !important;
}
.sortable-item {
border: 1px solid black;
margin: 0 !important;
}
.sortable-item > a {
display: block;
margin: 0 !important;
}
.sortable-item input {
display: block;
margin: 0 !important;
}
.sortable-container {
margin: 0 !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.0-beta.1/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul class="sortable sortable-grid" data-bind="template: { name: 'gridTmpl', foreach: gridItems, templateOptions: { parentList: gridItems} }, sortableList: gridItems">
</ul>
<script id="gridTmpl" type="text/html">
<li class="sortable-row">
<table style="width:100%">
<tbody>
<tr class="sortable sortable-container" data-bind="template: { name: 'rowTmpl', foreach: rowItems, templateOptions: { parentList: rowItems} }, sortableList: rowItems">
</tr>
</tbody>
</table>
</li>
</script>
<script id="rowTmpl" type="text/html">
<td class="sortable-item" data-bind="sortableItem: { item: $data, parentList: $data.parentList }">
<input data-bind="value: name, visibleAndSelect: $data === $root.selectedRowItem()" />
</td>
</script>
On your table, set table-layout to fixed. Another improvement would be to make the inputs take up the entire space of the cell.
Here are the css changes to make:
.sortable-item input {
display: block;
margin: 0 !important;
width: 100%; /* Added this property */
}
/* Added this rule */
.sortable-row > table {
table-layout: fixed;
}

Knock out- css binding to highlight areas with no text in them

I'm currently working on making a contacts editor but dont fully understand the knockout conditional css binding. Basically what i would like to have happen is when you click the Add employee button two text boxes are created to add a first and last name. I would like those fields to be highlighted using the knockout conditional css binding . I would like the same thing to happen when clicking the add number option.
here is my code
and a fiddle http://jsfiddle.net/grahamwalsh/c2fmnoub/
html
<div data-bind="if:!loaded()"> Loading...Please Wait</div>
<div class='NbiEmployees'data-bind="if:loaded()">
<h2>NBI Employees</h2>
<h3>NBI has <span data-bind="text: employees().length"></span> Employees</h3>
<div id='employeesList'>
<table class='employeesEditor'>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Phone numbers</th>
</tr>
<tbody data-bind="foreach: employees">
<tr>
<td>
<input data-bind='value: firstName' />
<div><a href='#' data-bind='click: $root.removeEmployee'>Delete</a></div>
</td>
<td><input data-bind='value: lastName' /></td>
<td>
<table>
<tbody data-bind="foreach: phones">
<tr>
<td><input data-bind='value: type' /></td>
<td><input data-bind='value: number' /></td>
<td><a href='#' data-bind='click: $root.removePhone'>Delete</a></td>
</tr>
</tbody>
</table>
<a href='#' data-bind='click: $root.addPhone'>Add number</a>
</td>
</tr>
</tbody>
</table>
</div>
<p>
<button data-bind='click: addEmployee'>Add an Employee</button>
<button data-bind='click: save, enable: employees().length > 0'>Save to JSON</button>
</p>
<textarea data-bind='value: lastSavedJson' rows='5' cols='60' disabled='disabled'> </textarea>
css
body { font-family: arial; font-size: 14px; }
.NbiEmployees { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; }
.NbiEmployees input { font-family: Arial; }
.NbiEmployees b { font-weight: bold; }
.NbiEmployees p { margin-top: 0.9em; margin-bottom: 0.9em; }
.NbiEmployees select[multiple] { width: 100%; height: 8em; }
.NbiEmployees h2 { margin-top: 0.4em; font-weight: bold; font-size: 1.2em; }
.NbiEmployees TR { vertical-align: top; }
.NbiEmployees TABLE, .NbiEmployees TD, .NbiEmployees TH { padding: 0.2em; border-width: 0; margin: 0; }
.NbiEmployees TD A { font-size: 0.8em; text-decoration: none; }
.NbiEmployees table.contactsEditor > tbody > TR { border-bottom: 1px solid silver; }
.NbiEmployees td input { width: 8em; }
li { list-style-type: disc; margin-left: 20px; }
Knockout
var EmployeesModel = function () {
var self = this;
self.employees = ko.observableArray(
);
self.loaded = ko.observable(false);
self.loadData = function loadData() {
self.loaded(false);
setTimeout(function () {
var data = [
{
firstName: "Graham", lastName: "Walsh", phones: [
{ type: "Office", number: "(555) 121-2121" },
{ type: "Mobile", number: "(555) 123-4567" }]
},
{
firstName: "Kimi", lastName: "Shirasaki", phones: [
{ type: "Office", number: "(555) 444-2222" },
{ type: "Mobile", number: "(555) 999-1212" }]
}
];
self.employees(ko.utils.arrayMap(data, function (employee) {
return {
firstName: employee.firstName,
lastName: employee.lastName,
phones: ko.observableArray(employee.phones)
};
}));
self.loaded(true);
}, 5000);
};
self.addEmployee = function () {
self.employees.push({
firstName: "",
lastName: "",
phones: ko.observableArray()
});
};
self.removeEmployee = function (employee) {
self.employees.remove(employee);
};
self.addPhone = function (employee) {
employee.phones.push({
type: "",
number: ""
});
};
self.removePhone = function (phone) {
$.each(self.employees(), function () { this.phones.remove(phone) })
};
self.save = function () {
self.lastSavedJson(JSON.stringify(ko.toJS(self.employees), null, 2));
};
self.lastSavedJson = ko.observable("")
self.loadData();
};
$(document).ready(function () {
ko.applyBindings(new EmployeesModel());
});
If you add something like this to the 'required' fields:
<input data-bind='value: firstName, css: {warn: !firstName()}' />
and then define your warn class:
.warn {
border-color: red;
}
then the field will be highlighted. However, for this to work, the fields have to be observable:
http://jsfiddle.net/c2fmnoub/14/
here, I've created an Employee() class with observable fields (except for the phone number, which can also be observable if needed), of which a new one needs to be created when calling the addEmployee() function
Edit: the phone number:
http://jsfiddle.net/c2fmnoub/16/
in the same way I defined an Employee object with observable fields, I defined a Phone object with observable fields. This should have been a simple extension for the OP to have done. I really hope I didn't just do your homework for you.

Resources