我正在研究我想要以下功能的迷你项目 -
点击HDFC Bank
行后,相关图表(显示公司在一段时间内的增长)会在下方显示。
我正试图通过在visible binding
内使用两个knockout.JS概念 - click binding
来解决这个问题。我试过这个如下 -
this.showGraph = ko.observable(false); //initially the graph <div> is invisible
self.drawGraph = function(company) {
//console.log(company.name+"=="+self.companyPortfolio()[0].name);
self.showGraph = ko.computed(function() {
return company.name == self.companyPortfolio()[0].name;
});
// console.log("showGraph="+self.showGraph());
}
我决定使用a stackoverflow post中的computed observables
。
以下是 HTML -
<table class="table table-hover">
<thead>
<tr>
<th>Company</th>
<th>Investment(%)</th>
<th>Nos</th>
<th>ABP</th>
<th>LTP</th>
<th><span class="glyphicon glyphicon-triangle-top"></span>Daily(%)</th>
<th>Total(%)</th>
<th>Value</th>
</tr>
</thead>
<tbody data-bind="foreach: companyPortfolio">
<tr>
<td data-bind="text: name,click: $parent.drawGraph"></td>
<td><span data-bind="text: investment"></span><span>(</span><span data-bind="text: investment_percentage"></span><span>%)</span></td>
<td data-bind="text: count"></td>
<td data-bind="text: avg_buy_price"></td>
<td data-bind="text: current_price"></td>
<td><span class="glyphicon glyphicon-triangle-top"></span><span data-bind="text: daily_percentage"></span><span>%</span></td>
<td><span data-bind="text: returns_percentage"></span><span>%</span></td>
<td data-bind="text: value"></td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col-md-12 col-xs-12">
<div id="chart2" data-bind="visible: showGraph"></div>
</div>
</div>
当我点击HDFC Bank
行时,我得到showGraph = true
这是预期的输出。
请参阅此处 -
问题 - 即使<div>
获得正确的值,图表showGraph observable
也会保持不可见。
我的代码 - GitHub repo
答案 0 :(得分:3)
drawGraph函数用每次被调用的新计算覆盖showGraph observable并没有多大意义。我不认为你真的需要一个计算的observable,因为你根据点击事件进行了更新。
尝试这样的事情:
self.showGraph = ko.observable(false);
self.drawGraph = function(company) {
self.showGraph(company.name == self.companyPortfolio()[0].name);
}
答案 1 :(得分:2)
问题实际上是由您在drawGraph
内嵌套计算引起的。计算真的不是必需的,但是我修改了你的代码,使其通过移动计算机并使你的点击事件设置为引用SelectedCompany
来起作用。
// Current_price is same as LTP (Last Traded Price)
// ABP stands for Average Buy Price
var portfolio = [{
"current_price": 1626.0,
"ticker_symbol": "HDFCBANK.NS",
"in_watchlist": true,
"valuation": "fair",
"symbol": "HDFCBANK",
"returns_percentage": 29.777877102106267,
"daily_percentage": 0.5,
"count": 5,
"marketcap": "Large Cap",
"name": "HDFC Bank",
"industry": "Financials",
"avg_buy_price": 1252.9100000000003
},
{
"current_price": 7064.8,
"ticker_symbol": "MARUTI.NS",
"in_watchlist": false,
"valuation": "attractive",
"symbol": "MARUTI",
"returns_percentage": 14.961719023326577,
"daily_percentage": 1.1,
"count": 1,
"marketcap": "Large Cap",
"name": "Maruti Suzuki",
"industry": "Automobiles",
"avg_buy_price": 6145.35
},
{
"current_price": 1091.15,
"ticker_symbol": "EMAMILTD.NS",
"in_watchlist": true,
"valuation": "fair",
"symbol": "EMAMILTD",
"returns_percentage": 7.405463046509734,
"daily_percentage": 0.1,
"count": 6,
"marketcap": "Large Cap",
"name": "Emami",
"industry": "FMCG",
"avg_buy_price": 1015.9166666666666
},
{
"current_price": 1493.6,
"ticker_symbol": "YESBANK.NS",
"in_watchlist": true,
"valuation": "unattractive",
"symbol": "YESBANK",
"returns_percentage": 5.1942106560552,
"daily_percentage": 2.0,
"count": 4,
"marketcap": "Large Cap",
"name": "Yes Bank",
"industry": "Financials",
"avg_buy_price": 1419.8500000000001
},
{
"current_price": 1477.7,
"ticker_symbol": "INDUSINDBK.NS",
"in_watchlist": false,
"valuation": "fair",
"symbol": "INDUSINDBK",
"returns_percentage": 20.33265133701815,
"daily_percentage": 1.1,
"count": 4,
"marketcap": "Large Cap",
"name": "Indusind Bank",
"industry": "Financials",
"avg_buy_price": 1228.0125
}
];
var hdfc_stock_data = {
"stock": {
"stock_price": "1,626",
"growth_history": [{
"growth": 0.5,
"label": "1 Day"
},
{
"growth": 4.1,
"label": "1 Week"
},
{
"growth": 4.7,
"label": "1 Mo"
},
{
"growth": 38.5,
"label": "1 Yr"
},
{
"growth": 27.6,
"label": "5 Yr"
},
{
"growth": 22.5,
"label": "10 Yr"
}
],
"short_name": "HDFC Bank",
"industry_name": "Bank - Private",
"current_price": "1,626",
"yearly_growth": 17.3,
"symbol": "HDFCBANK",
"industry": "Financials > Bank - Private",
"graphs": {
"stock_price": {
"values": [
null, null, null, 189.959795109746, 197.71928584431, 219.970607249454, 307.678835624819, 281.625310309537, 249.119276388136, 227.100294661012, 188.794277595195, 169.215123451412, 258.013509416648, 276.27126381467, 322.691660573649, 323.487845020358, 367.61921149505, 405.780443764135, 447.07583943518, 409.987251223347, 448.565660818427, 461.007917141224, 437.402813351776, 488.791340421378, 509.46681790125, 572.204908113496, 626.12896425413, 635.592297266244, 659.238528347662, 617.448102158967, 647.100254100593, 654.104507275281, 776.032203654182, 825.764714228535, 911.757260470622, 1036.6605724851, 997.749806712709, 1065.40547367068, 1068.48023694246, 1021.91245126184, 1133.84375294572, 1247.825, 1220.8, 1318.15, 1626.0
]
},
"x_axis": {
"values": [
"Mar06", "Jun06", "Sep06", "Dec06", "Mar07", "Jun07", "Sep07", "Dec07", "Mar08", "Jun08", "Sep08", "Dec08", "Mar09", "Jun09", "Sep09", "Dec09", "Mar10", "Jun10", "Sep10", "Dec10", "Mar11", "Jun11", "Sep11", "Dec11", "Mar12", "Jun12", "Sep12", "Dec12", "Mar13", "Jun13", "Sep13", "Dec13", "Mar14", "Jun14", "Sep14", "Dec14", "Mar15", "Jun15", "Sep15", "Dec15", "Mar16", "Jun16", "Sep16", "Dec16", "Mar17"
]
}
}
}
};
var points = hdfc_stock_data.stock.graphs.stock_price.values;
//console.log(points);
var xAxis = hdfc_stock_data.stock.graphs.x_axis.values;
//console.log(xAxis);
var growthDetails = hdfc_stock_data.stock.growth_history;
function graph(line) {
var plot2 = $.jqplot('chart2', [line], {
// title:'Customized Date Axis',
grid: {
drawGridlines: false
},
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
labelRenderer: $.jqplot.CanvasAxisLabelRenderer,
tickRenderer: $.jqplot.CanvasAxisTickRenderer,
tickOptions: {
angle: 45,
}
},
yaxis: {
tickOptions: {
show: false
},
rendererOptions: {
drawBaseline: false
}
},
series: [{
lineWidth: 4,
markerOptions: {
style: 'square'
}
}]
}
});
}
$(document).ready(function() {
// Broken
//$.jqplot.config.enablePlugins = true;
//var line = [];
//points.forEach(function(point, index) {
// line.push([xAxis[index], point]);
//})
//graph(line);
})
ko.extenders.numeric = function(target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko.pureComputed({
read: target, //always return the original observables value
write: function(newValue) {
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? 0 : +newValue,
valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({
notify: 'always'
});
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
var growthHistory = function(data) {
this.growth = data.growth;
this.label = data.label;
}
var derivedPortfolio = function(data) {
this.name = data.name;
this.investment = ko.observable(data.avg_buy_price * data.count).extend({
numeric: 0
});
this.investment_percentage = ko.observable((data.avg_buy_price * data.count) / 1000).extend({
numeric: 1
});
this.count = data.count;
this.avg_buy_price = ko.observable(data.avg_buy_price).extend({
numeric: 0
});
this.current_price = ko.observable(data.current_price).extend({
numeric: 0
});
this.daily_percentage = ko.observable(data.daily_percentage).extend({
numeric: 1
});
this.returns_percentage = ko.observable(data.returns_percentage).extend({
numeric: 1
});
this.value = ko.observable(data.current_price * data.count).extend({
numeric: 0
});
}
//viewModel
var viewModel = function() {
var self = this; //self is refer to as viewModel
this.companyPortfolio = ko.observableArray([]);
this.companyGrowth = ko.observableArray([]);
this.showGraph = ko.observable(false);
//console.log("showGraph=" + self.showGraph());
portfolio.forEach(function(info, index) {
self.companyPortfolio.push(new derivedPortfolio(info));
});
//console.log(self.companyPortfolio());
// self.companyPortfolio().forEach(function(info,index) {
// console.log("investment--"+info.investment());
// console.log("investment--"+info.investment_percentage());
// // info.avg_buy_price = ko.observable(info.avg_buy_price).extend({numeric:0});
// console.log("avg_buy_price--"+info.avg_buy_price());
// });
growthDetails.forEach(function(info, index) {
self.companyGrowth.push(new growthHistory(info));
});
//console.log(self.companyGrowth());
self.SelectedCompany = ko.observable();
self.drawGraph = function(company) {
console.log(company.name + "==" + self.companyPortfolio()[0].name);
self.SelectedCompany(company.name);
}
self.showGraph = ko.computed(function() {
return self.SelectedCompany() == self.companyPortfolio()[0].name;
});
//console.log("showGraph=" + self.showGraph());
}
ko.applyBindings(new viewModel);
&#13;
.hidden {
display: none;
}
/*rules for the plot target div. These will be cascaded down to all plot elements according to css rules*/
.jqplot-target {
position: relative;
color: #666666;
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
font-size: 1em;
/* height: 300px;
width: 400px;*/
}
/*rules applied to all axes*/
.jqplot-axis {
font-size: 0.75em;
}
.jqplot-xaxis {
margin-top: 10px;
}
.jqplot-x2axis {
margin-bottom: 10px;
}
.jqplot-yaxis {
margin-right: 10px;
}
.jqplot-y2axis,
.jqplot-y3axis,
.jqplot-y4axis,
.jqplot-y5axis,
.jqplot-y6axis,
.jqplot-y7axis,
.jqplot-y8axis,
.jqplot-y9axis,
.jqplot-yMidAxis {
margin-left: 10px;
margin-right: 10px;
}
/*rules applied to all axis tick divs*/
.jqplot-axis-tick,
.jqplot-xaxis-tick,
.jqplot-yaxis-tick,
.jqplot-x2axis-tick,
.jqplot-y2axis-tick,
.jqplot-y3axis-tick,
.jqplot-y4axis-tick,
.jqplot-y5axis-tick,
.jqplot-y6axis-tick,
.jqplot-y7axis-tick,
.jqplot-y8axis-tick,
.jqplot-y9axis-tick,
.jqplot-yMidAxis-tick {
position: absolute;
white-space: pre;
}
.jqplot-xaxis-tick {
top: 0px;
/* initial position untill tick is drawn in proper place */
left: 15px;
/* padding-top: 10px;*/
vertical-align: top;
}
.jqplot-x2axis-tick {
bottom: 0px;
/* initial position untill tick is drawn in proper place */
left: 15px;
/* padding-bottom: 10px;*/
vertical-align: bottom;
}
.jqplot-yaxis-tick {
right: 0px;
/* initial position untill tick is drawn in proper place */
top: 15px;
/* padding-right: 10px;*/
text-align: right;
}
.jqplot-yaxis-tick.jqplot-breakTick {
right: -20px;
margin-right: 0px;
padding: 1px 5px 1px 5px;
/*background-color: white;*/
z-index: 2;
font-size: 1.5em;
}
.jqplot-y2axis-tick,
.jqplot-y3axis-tick,
.jqplot-y4axis-tick,
.jqplot-y5axis-tick,
.jqplot-y6axis-tick,
.jqplot-y7axis-tick,
.jqplot-y8axis-tick,
.jqplot-y9axis-tick {
left: 0px;
/* initial position untill tick is drawn in proper place */
top: 15px;
/* padding-left: 10px;*/
/* padding-right: 15px;*/
text-align: left;
}
.jqplot-yMidAxis-tick {
text-align: center;
white-space: nowrap;
}
.jqplot-xaxis-label {
margin-top: 10px;
font-size: 11pt;
position: absolute;
}
.jqplot-x2axis-label {
margin-bottom: 10px;
font-size: 11pt;
position: absolute;
}
.jqplot-yaxis-label {
margin-right: 10px;
/* text-align: center;*/
font-size: 11pt;
position: absolute;
}
.jqplot-yMidAxis-label {
font-size: 11pt;
position: absolute;
}
.jqplot-y2axis-label,
.jqplot-y3axis-label,
.jqplot-y4axis-label,
.jqplot-y5axis-label,
.jqplot-y6axis-label,
.jqplot-y7axis-label,
.jqplot-y8axis-label,
.jqplot-y9axis-label {
/* text-align: center;*/
font-size: 11pt;
margin-left: 10px;
position: absolute;
}
.jqplot-meterGauge-tick {
font-size: 0.75em;
color: #999999;
}
.jqplot-meterGauge-label {
font-size: 1em;
color: #999999;
}
table.jqplot-table-legend {
margin-top: 12px;
margin-bottom: 12px;
margin-left: 12px;
margin-right: 12px;
}
table.jqplot-table-legend,
table.jqplot-cursor-legend {
background-color: rgba(255, 255, 255, 0.6);
border: 1px solid #cccccc;
position: absolute;
font-size: 0.75em;
}
td.jqplot-table-legend {
vertical-align: middle;
}
/*
These rules could be used instead of assigning
element styles and relying on js object properties.
*/
/*
td.jqplot-table-legend-swatch {
padding-top: 0.5em;
text-align: center;
}
tr.jqplot-table-legend:first td.jqplot-table-legend-swatch {
padding-top: 0px;
}
*/
td.jqplot-seriesToggle:hover,
td.jqplot-seriesToggle:active {
cursor: pointer;
}
.jqplot-table-legend .jqplot-series-hidden {
text-decoration: line-through;
}
div.jqplot-table-legend-swatch-outline {
border: 1px solid #cccccc;
padding: 1px;
}
div.jqplot-table-legend-swatch {
width: 0px;
height: 0px;
border-top-width: 5px;
border-bottom-width: 5px;
border-left-width: 6px;
border-right-width: 6px;
border-top-style: solid;
border-bottom-style: solid;
border-left-style: solid;
border-right-style: solid;
}
.jqplot-title {
top: 0px;
left: 0px;
padding-bottom: 0.5em;
font-size: 1.2em;
}
table.jqplot-cursor-tooltip {
border: 1px solid #cccccc;
font-size: 0.75em;
}
.jqplot-cursor-tooltip {
border: 1px solid #cccccc;
font-size: 0.75em;
white-space: nowrap;
background: rgba(208, 208, 208, 0.5);
padding: 1px;
}
.jqplot-highlighter-tooltip,
.jqplot-canvasOverlay-tooltip {
border: 1px solid #cccccc;
font-size: 0.75em;
white-space: nowrap;
background: rgba(208, 208, 208, 0.5);
padding: 1px;
}
.jqplot-point-label {
font-size: 0.75em;
z-index: 2;
}
td.jqplot-cursor-legend-swatch {
vertical-align: middle;
text-align: center;
}
div.jqplot-cursor-legend-swatch {
width: 1.2em;
height: 0.7em;
}
.jqplot-error {
/* Styles added to the plot target container when there is an error go here.*/
text-align: center;
}
.jqplot-error-message {
/* Styling of the custom error message div goes here.*/
position: relative;
top: 46%;
display: inline-block;
}
div.jqplot-bubble-label {
font-size: 0.8em;
/* background: rgba(90%, 90%, 90%, 0.15);*/
padding-left: 2px;
padding-right: 2px;
color: rgb(20%, 20%, 20%);
}
div.jqplot-bubble-label.jqplot-bubble-label-highlight {
background: rgba(90%, 90%, 90%, 0.7);
}
div.jqplot-noData-container {
text-align: center;
background-color: rgba(96%, 96%, 96%, 0.3);
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table class="table table-hover">
<thead>
<tr>
<th>Company</th>
<th>Investment(%)</th>
<th>Nos</th>
<th>ABP</th>
<th>LTP</th>
<th><span class="glyphicon glyphicon-triangle-top"></span>Daily(%)</th>
<th>Total(%)</th>
<th>Value</th>
</tr>
</thead>
<tbody data-bind="foreach: companyPortfolio">
<tr>
<td data-bind="text: name,click: $parent.drawGraph"></td>
<td><span data-bind="text: investment"></span><span>(</span><span data-bind="text: investment_percentage"></span><span>%)</span></td>
<td data-bind="text: count"></td>
<td data-bind="text: avg_buy_price"></td>
<td data-bind="text: current_price"></td>
<td><span class="glyphicon glyphicon-triangle-top"></span><span data-bind="text: daily_percentage"></span><span>%</span></td>
<td><span data-bind="text: returns_percentage"></span><span>%</span></td>
<td data-bind="text: value"></td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col-md-12 col-xs-12">
<div id="chart2" data-bind="visible: showGraph()">
Here is the graph div
</div>
</div>
</div>
&#13;