Knockout not updating the Viewmodel - knockout-2.0

I have a knockout script that have a defaut viewmodel with few fields values. When I have entered the data in the form and submit, it is not sending any updated value back. For example, the zipcode stays the value I defined on the defaul load. Here is the code
$(function () {
ViewModel.zipCode.subscribe(function (value) {
$.get("/api/abc/GetCounties?zipCode=" + value, null, ViewModel.county, 'json');
}.bind(this));
});
var ViewModel = function (data) {
var self = this;
self.zipCode = ko.observable(data.zipCode);
self.dateOfEvent = ko.observable(new Date());
//Enrollment reasons
self.enrollmentReasons = ko.observableArray(new Array());
$.get("/api/abc/reasons", null, self.enrollmentReasons, 'json');
//county from Zipcode subscribed
self.county = ko.observableArray(new Array());
$.get("/api/utilityapi/GetCounties?zipCode=" + data.zipCode, null, self.county, 'json');
self.selectedChoice = ko.observable();
self.applicants = ko.observableArray();
self.applicants.push(new getaquoteapplicant());
//IsValid zip subscribed
self.isValidZip = ko.observable(false);
//operations
self.addApplicant = function () { self.applicants.push(new getaquoteapplicant()) };
self.removeApplicant = function (getaquoteapplicant) { self.applicants.remove(getaquoteapplicant) };
self.save = function () {
$.ajax({
url: '/xyz/start',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(data),
success: function (result) {
window.location.replace('/getaquote/planoptions', result);
}
});
}
}
var getaquoteapplicant = function () {
var self = this;
self.coverageFor = [
{ name: "Self" },
{ name: "Spouse/Life Partner" },
{ name: "Son" }
];
self.dateofBirth = ko.observable();
self.tobaccoUser = [
{ name: "Yes", value: true },
{ name: "No", value: false }
];
};
var defaultmodel = {
dateOfEvent: new Date(),
selectedChoice: 4,
zipCode:55044
}
ViewModel = new ViewModel(defaultmodel);
ko.applyBindings(ViewModel);
`

The problem could be that you are running the knockout binding even before the page is loaded or that you trying to access the ViewModel before it is created in the code execution order. One last thing is that always better to create a new instance of the model rather than the assigning it to itself.
I have created them in the fiddle below. It seems to work
https://jsfiddle.net/ramkiFiddle/npsgq8uL/1/
$(document).ready(function() {
var viewModel = new ViewModel(defaultmodel);
ko.applyBindings(viewModel);
});

Related

Reload page content if database variable has changed Meteor

I am working on meteor app. I want to reload the content of the client when the database variable has changed. I am using pub-sub. I want to load content if the status variable has changed.
Meteor.publish('activities', function(loggedInUserToken) {
var authObj = AuthenticationToken.findOne({ authToken: loggedInUserToken });
if (authObj) {
var userObj = Users.findOne({ _id: authObj.user_id });
var activities = Activities.find({}, { sort: { createdAt: -1 } });
return activities;
}
return this.ready();
});
Template.masterSku.onCreated(function() {
var instance = this;
instance.autorun(function() {
var loggedInUserToken = "xxxxxxxxxxxxxxxx"
statusSuscription = instance.subscribe("activities", loggedInUserToken);
var activitiesObj = Activities.findOne({}, { sort: { createdAt: -1 } })
if (activitiesObj && activitiesObj.status == "true") {
console.log("Status Changed load Content accordingly")
}
})
The autorun will not recompute until a reactive data has changed AND this change is requested within the computation. While a subscription is a reactive source, you also need to check for it's readyness and thus cause a new computation cycle:
instance.autorun(function() {
var loggedInUserToken = "xxxxxxxxxxxxxxxx"
var statusSuscription = instance.subscribe("activities", loggedInUserToken);
if (statusSuscription.ready()) { // causes a new compuation by the Tracker
var activitiesObj = Activities.findOne({}, { sort: { createdAt: -1 } })
if (activitiesObj && activitiesObj.status == "true") {
console.log("Status Changed load Content accordingly")
// here you can insert data into a ReactiveVar or ReactiveDict and use
// result in a Template helper, which itself will cause your Template to re-render
}
}
}
You can use Tracker in onCreated function OR you can try fill data through helpers.
import { Tracker } from 'meteor/tracker';
Tracker.autorun(() => {
var loggedInUserToken = "xxxxxxxxxxxxxxxx"
statusSuscription = instance.subscribe("activities", loggedInUserToken);
var activitiesObj = Activities.findOne({}, { sort: { createdAt: -1 } })
if (activitiesObj && activitiesObj.status == "true") {
console.log("Status Changed load Content accordingly")
}
});

Trouble with asynchronous requests pulling data from SQL database in Microsoft Bot Framework

I have a bot in the Microsoft bot Framework that I want to be able to pull data from an azure SQL database in order to answer questions asked to the bot. I have set up the database and it has some excel files in it.
Here is my code right now:
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var connection = new Connection(dataconfig);
connection.on('connect', function(err) {
console.log("Connected");
executeStatement();
});
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
function executeStatement() {
request = new Request("select \"Product Name\" from SPA_Data_Feeds where \"Strategic Priority\" = 'Accelerate to Value (LD)'",
function(err, rowCount, rows)
{
console.log(rowCount + ' row(s) returned');
}
);
var result = "";
var count = 0
request.on('row', function(columns) {
columns.forEach(function(column) {
console.log("%s\t", column.value);
result+= column.value + "\t\n";
count++;
if ( count == rowCount ) {
ATVData(result);
} ;
});
});
connection.execSql(request);
}
function ATVData(result) { //Puts "result" inside of an adaptive card }
I cant seem to figure out how to get the if statement right. rowCount does not work because it does not wait for it to be defined by the function before first, and I have tried using things like column(s).length, result(s).length but none work.
Is there something else I could use that would complete the if statement? Or do I need to reformat somehow with callbacks/promises to get it to wait for rowCount to be defined? If so could I get some advice on that?
Is there something else I could use that would complete the if statement? Or do I need to reformat somehow with callbacks/promises to get it to wait for rowCount to be defined? If so could I get some advice on that?
We can use Q.js which is one of the JavaScript Promise implementation to solve this issue. For example:
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var q = require('q');
// Create connection to database
var config =
{
userName: '', // update me
password: '', // update me
server: '', // update me
options:
{
database: '' //update me
, encrypt: true
}
}
var connection = new Connection(config);
// Attempt to connect and execute queries if connection goes through
connection.on('connect', function(err)
{
if (err)
{
console.log(err)
}
else
{
queryDatabase().then(function(result){
ATVData(result);
}, function(err){
console.log(err);
});
}
}
);
function queryDatabase()
{
console.log('Reading rows from the Table...');
//create a promise
var deferred = q.defer();
// Read all rows from table
var result = [];
var request = new Request(
"SELECT * From ForumMessages",
function(err, rowCount)
{
deferred.resolve(result);
});
request.on('row', function(columns) {
columns.forEach(function(column) {
console.log("%s\t%s", column.metadata.colName, column.value);
result.push(columns);
});
});
connection.execSql(request);
//return the promise
return deferred.promise;
}
function ATVData(result){
//your bot code goes here
}
I think to expand on Grace's answer, for each row, you can also do this for some utility:
request.on('row', function(columns) {
var singleResult = {};
columns.forEach(function(column) {
console.log("%s\t%s", column.metadata.colName, column.value);
// Add a property to the singleResult object.
singleResult[column.metadata.colName] = column.value;
// Push the singleResult object to the array.
result.push(singleResult);
});
});
Then you can, in your bot's code, call each object by the property name in dot notation, for example: result[x].colName where colName is the name of the column (or object property in this case).
Example (assuming at least one result item from the database, with a "link" column that has data):
var adaptiveCardExample = {
'contentType': 'application/vnd.microsoft.card.adaptive',
'content': {
'$schema': 'http://adaptivecards.io/schemas/adaptive-card.json',
'type': 'AdaptiveCard',
'version': '1.0',
'body': [
{
"type": "TextBlock",
"text": "Code Example"
},
{
"type": "TextBlock",
"text": "We're going to " + result[0].link,
"wrap": true
}],
'actions': [
{
'type': 'Action.OpenUrl',
'title': 'Go to the example link',
'url': result[0].link
}
]
}
};
var adaptiveCardMsg = new builder.Message(session).addAttachment(adaptiveCardExample);
session.send(adaptiveCardMsg);
You may want to add a check for null or undefined for the property in the case it is a nullable field in the database, as a precaution.

Use Socket.io to fill google Area Chart - 'google.visualization.DataTable is not a constructor'

I use NodeJS and Socket.io to get data from a database. I now want to fill a google area chart with these data but i kind of fail at doing it.
The data is transmitted as Objects. Each Object contains two values (datetime and value). I append these values to an array and then store them in a DataTable:
google.load('visualization', '1', {
packages: ['corechart']
});
google.setOnLoadCallback(drawChart);
var socket = io();
getData();
function drawChart(dataArray) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'DateTime');
data.addColumn('number', 'Value');
for (var i = 0; i < dataArray.length; i += 2) {
console.log(dataArray[0]);
data.addRow([dataArray[i], dataArray[i + 1]]);
}
var chart = new google.visualization.AreaChart(document.getElementById('chart'));
chart.draw(data, {
title: "Data Visualization",
isStacked: true,
width: '50%',
height: '50%',
vAxis: {
title: 'Data v-Axis'
},
hAxis: {
title: 'Data h-Axis'
}
})
}
function getData() {
socket.emit('GET');
socket.on('serverSent', function (data) {
var processedData = processData(data);
drawChart(processedData);
})
}
function processData(data) {
var arr = new Array();
jQuery.each(data, function (index, object) {
arr.push(object['datetime'], parseInt(object['value']));
})
return arr;
}
If i call my website i see the chart but without any values and the error message `google.visualization.DataTable is not a constructor´. So what am i doing wrong?
The problem is drawChart is being called twice.
From both google.setOnLoadCallback and getData.
If getData is called before google.setOnLoadCallback,
then google.visualization.DataTable will not be recognized.
In addition, it is recommended to use loader.js vs. jsapi.
See Load the Libraries for more info...
As such, please try the following...
Replace...
<script src="https://www.google.com/jsapi"></script>
With...
<script src="https://www.gstatic.com/charts/loader.js"></script>
And try something like...
google.charts.load('current', {
callback: init,
packages: ['corechart']
});
function init() {
var socket = io();
socket.emit('GET');
socket.on('serverSent', function (data) {
var processedData = processData(data);
drawChart(processedData);
});
}
function drawChart(dataArray) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'DateTime');
data.addColumn('number', 'Value');
for (var i = 0; i < dataArray.length; i += 2) {
console.log(dataArray[0]);
data.addRow([dataArray[i], dataArray[i + 1]]);
}
var chart = new google.visualization.AreaChart(document.getElementById('chart'));
chart.draw(data, {
title: "Data Visualization",
isStacked: true,
width: '50%',
height: '50%',
vAxis: {
title: 'Data v-Axis'
},
hAxis: {
title: 'Data h-Axis'
}
})
}

Variable precedence (global in node js?)

"use strict";
var Tabletop = require("tabletop");
var base64 = require('base-64');
Tabletop.init( { key: 'xxxxxg46hgfjd',
callback: showInfo,
simpleSheet: true } )
function showInfo(data, tabletop) {
console.log(data);
console.log(base64.encode(data));
}
var vGlobals = {
dataString: base64.encode(data)
};
module.exports = vGlobals;
How can I access the data variable from showInfo, to use in vGlobals? It says that it hasn't been defined.
Your approach is wrong, you can't do it this way because TableTop call your callback asynchronously.
My suggestion (a quick one) :
var dataString = null;
module.exports = function(cb) {
if (dataString == null)
Tabletop.init({
key: 'xxxxxg46hgfjd',
callback: function(data, tabletop) {
dataString = base64.encode(data);
cb(dataString);
},
simpleSheet: true
});
else cb(dataString);
};
And to get the data :
var dataManager = require('./myfile');
dataManager(function(dataString) {
//here is your data do what you want with it
})
You should look/learn more about node/javascript and asynchronous/event-driven programing.

Kendo Grid - problems with search in database

My controller like this:
[HttpPost]
public ActionResult Error_Search([DataSourceRequest] DataSourceRequest request, object[] ParaSearch)
{
object[] obj = new object[5];
obj[0] = Convert.ToInt32(ParaSearch[0]);
obj[1] = ParaSearch[1].ToString();
obj[2] = Convert.ToDateTime(ParaSearch[2]).AddDays(-10);
obj[3] = Convert.ToDateTime(ParaSearch[3]);
obj[4] = ParaSearch[4];
List<Vsoft.Lists.Model.SYS.SYS_Error> lst = new List<Vsoft.Lists.Model.SYS.SYS_Error>();
ResultMessage result = new Vsoft.Lists.DALEntity.SYS.DAL_Error().SelectToList(ref lst, obj);
return Json(lst.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
It will return Json(lst) correct.. but I can't bind it to datasource and refresh Grid after Ajax Call like this :
var requestData = { ParaSearch: arrObject };
$.ajax({
url: '#Url.Content("~/Error/Error_Search")',
data: JSON.stringify(requestData),
type: 'POST',
traditional: true,
dataType: 'json',
contentType: 'application/json; charset=utf-8',
error: function (xhr) {
result = false;
alert('Error: ' + xhr.statusText);
},
success: function (lst) {
var grid = $("#Grid").data("kendoGrid");
grid.dataSource.data(lst);
grid.refresh();
},
async: true,
processData: false,
cache: false
});
Can AnyOne help me to solve this ?
Thanks All !
If ajax return is good enough, then using setDatasource api call should be your friend.
success: function (lst) {
var grid = $("#Grid").data("kendoGrid");
var dataSource = new kendo.data.DataSource({
data: lst });
grid.setDataSource(dataSource);
}
EDIT: using read (read is just wrapper over $.ajax)
Hope you have configured your grid like:
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Error_Search", "Error", new { ParaSearch = []}))
)
Then, wire up some event from where ParaSearch is originating and use read call as:
<script>
function someEvent(e) {
var requestData = { ParaSearch: arrObject };
grid.dataSource.read(requestData);
}
</script>

Resources