knockout.JS中的可见绑定与点击绑定一起使用

时间:2017-07-25 17:32:38

标签: javascript html knockout.js

我正在研究我想要以下功能的迷你项目 - 点击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这是预期的输出。

请参阅此处 -

enter image description here

问题 - 即使<div>获得正确的值,图表showGraph observable也会保持不可见

我的代码 - GitHub repo

2 个答案:

答案 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来起作用。

&#13;
&#13;
// 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;
&#13;
&#13;