The link in the first td
column spazzes out when trying to bind to $root.rootBaseUrl
.
In the second td
column, the same rootBaseUrl
observable prints perfectly.
The difference is that in the first td
column, I am trying to set the value within attr:
.
Also, please note that there is a foreach
loop happening at the tbody
level. Hence the use of $root
prefix.
<tbody data-bind="foreach: siteList">
<tr>
<td><h3><a data-bind="text: SiteName, attr: {href: $root.rootBaseUrl + SiteID}"></a></h3></td>
<td><h3><span data-bind="text: $root.rootBaseUrl"></span></h3></td>
</tr>
</tbody>
var rootBaseUrl = ko.observable("");
var index = window.location.toString().indexOf("RiskOrder");
var baseURL = window.location.toString().substring(0, index);
this.rootBaseUrl(baseURL);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
Basically, I am getting the current browser URL in the JS, stripping it to the base root url, then trying to add this static URL to the href
binding and concatenating with a dynamic SiteID
value.
Is this possible?
Replace attr
with text
and get a glimplse of your problem:
function Vm(){
var self = this;
self.SiteID = ko.observable("AX123");
}
function RootVm(){
var self = this;
var index = window.location.toString().indexOf("RiskOrder");
var baseURL = window.location.toString().substring(0, index);
self.rootBaseUrl = ko.observable("");
self.SiteName = ko.observable("My Site");
self.rootBaseUrl(baseURL);
self.SiteList = ko.observableArray([new Vm()]);
}
ko.applyBindings(new RootVm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
<tbody data-bind="foreach: SiteList">
<tr>
<td>
<h3><a data-bind="text: $root.rootBaseUrl + SiteID"></a></h3>
</td>
<td>
<h3><span data-bind="text: $root.rootBaseUrl"></span></h3>
</td>
</tr>
</tbody>
</table>
It renders function.....
, so a textual representation of a function. This is because rootBaseUrl
is a function. If you want to use it in an expression, you have to use parentheses:
<h3><a data-bind="text: $root.rootBaseUrl()+ SiteID()"></a></h3>
If you use it as the only thing in a binding, the parentheses are optional:
<h3><span data-bind="text: $root.rootBaseUrl()"></span></h3>
So your fix would be:
function Vm(){
var self = this;
self.SiteID = ko.observable("AX123");
self.SiteName = ko.observable("My Site");
}
function RootVm(){
var self = this;
var index = window.location.toString().indexOf("RiskOrder");
var baseURL = window.location.toString().substring(0, index);
// On SO Snippets window.location works differently so we hack it:
baseURL = "https://example.com/my-website/url/";
self.rootBaseUrl = ko.observable("");
self.rootBaseUrl(baseURL);
self.SiteList = ko.observableArray([new Vm()]);
}
ko.applyBindings(new RootVm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
<tbody data-bind="foreach: SiteList">
<tr>
<td>
<h3><a data-bind="text: SiteName, attr: { href: $root.rootBaseUrl() + SiteID() }"></a></h3>
</td>
<td>
Second column
</td>
</tr>
</tbody>
</table>
Or use a computed so you can (a) unit test the logic and (b) make the parentheses optional again:
function Vm(urlBaseVm){
var self = this;
self.SiteID = ko.observable("AX123");
self.SiteName = ko.observable("My Site");
self.hrf = ko.computed(function() {
return urlBaseVm.rootBaseUrl() + self.SiteID();
});
}
function RootVm(){
var self = this;
var index = window.location.toString().indexOf("RiskOrder");
var baseURL = window.location.toString().substring(0, index);
// On SO Snippets window.location works differently so we hack it:
baseURL = "https://example.com/my-website/url/";
self.rootBaseUrl = ko.observable("");
self.rootBaseUrl(baseURL);
self.SiteList = ko.observableArray([new Vm(self)]);
}
ko.applyBindings(new RootVm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
<tbody data-bind="foreach: SiteList">
<tr>
<td>
<h3><a data-bind="text: SiteName, attr: { href: hrf }"></a></h3>
</td>
<td>
Second column
</td>
</tr>
</tbody>
</table>