Now I'm writing a simple application which get five photos from Flickr and display the titles as list. At first I tried #current_photos and this works good, but when I use Knockout.js(#currentPhotos), this doesn't work.
root = exports ? this
class root.Flickr
constructor: ->
#photos = []
$.getJSON(
'http://www.flickr.com/services/rest/?jsoncallback=?'
format : 'json'
method : 'flickr.photos.search'
api_key : '7965a8bc5a2a88908e8321f3f56c80ea'
user_id : '29242822#N00'
per_page : 5
).done((data) =>
$.each data.photos.photo, (i, item) =>
#photos.push item
)
root = exports ? this
class root.PhotoListViewModel
index = null
currentPhotos = []
constructor: ->
flickr = new Flickr
# #current_photos = flickr.photos ###### WORKS GOOD
flickr.photos = ko.observableArray []
#currentPhotos = ko.computed ->
flickr.photos
HTML is as below:
<body>
<h4>Photo List</h4>
<ul data-bind="foreach: currentPhotos">
<li>
title: <span data-bind="text: title"> </span>
</li>
</ul>
</body>
I created JSBin page as below:
http://jsbin.com/avazak/7/
Thanks for your kindness.
Because of how the dependency tracking works in computed observable:
While your evaluator function is running, KO keeps a log of any observables (or computed observables) that your evaluator reads the value of.
So you need to call your observables inside the computed it is not enough the reference them:
#currentPhotos = ko.computed ->
flickr.photos()
And I would suggets that you declare the #photos as ko.observableArray inside the Flickr object not in the PhotoListViewModel
Demo JSFiddle.
Related
I have a div with controller like this
<div ng-controller= "merchandiseListCtrl as ml">
In the js file, I have a couple of function calls and render an object on return.
vm.getlaptopTotal = (productCatergory) => getTotal(productCatergory);
var getTotal = function (_) {
var res = {
count: 0,
total: 0,
products: []
};
_.map((item) =>{
if(item.purchased){
res.count += 1;
res.total += item.price;
res.products.push(item.product);
}
});
return res;
};
So, it is obvious that I'm returning obj res with properties: count, total, and products.
In the HTML view template, I want to have to shorter namespace, shortcut to reduce the pattern ml.fn(x).products of my function call to return the properties' values for some fields. In other words, I want to assign something like ng-bind ='myTotal = ml.fn(x)', but then I run into ton of errors about $rootScope. What should I do to have a better namespace for this scenario, and complexity may go this far: funcObj.subobj.property.childproperty.grandchildproperty ? So accessibility and readibility can be accomplished?
Here is my HTML code
<div>{{ml.myTotal = ml.getlaptopTotal(ml.laptops)}}>
<!-- display the selection -->
Laptop count: {{ ml.myTotal.count }} units
<br>
<div ng-if="ml.myTotal.products">
<ul ng-repeat="product in ml.myTotal.products">
<li>{{$index+1}}) {{product}}</li>
</ul>
</div>
<br>
</div>
EDIT 1: Ran into this error because now the products array, funcObj().products is dynamic. Don't know how to fix yet. But previously, I use funcObj() as an ng-click event handler.
Thanks,
I would like to get the result of value conventer that filters an array in my view in order to display the number of results found.
<div repeat.for="d of documents|docfilter:query:categories">
<doc-template d.bind="d"></doc-template>
</div>
I neither want to move this logic to my controller (to keep it clean), nor to add crutches like returning some data from the value controller.
What I want:
So, basically I would like something like angular offers:
Like shown here:
ng-repeat="item in filteredItems = (items | filter:keyword)"
or here: ng-repeat="item in items | filter:keyword as filteredItems"
What I get:
Unfortunately, in Aurelia:
d of filteredDocuments = documents|docfilter:query:categories
actually means d of filteredDocuments = documents |docfilter:query:categories, and if I add brackets or as, it won't run (fails with a parser error).
So,
Is there a clean way of getting data out of data-filter in view?
Best regards, Alexander
UPD 1: when I spoke about returning some data from the value controller I meant this:
export class DocfilterValueConverter {
toView(docs, query, categories, objectToPassCount) {
...
objectToPassCount.count = result.length;
...
});
});
UPD 2. Actually, I was wrong about this: d of filteredDocuments = documents |docfilter:query:categories. It does not solve the issue but what this code does is :
1) filteredDocuments = documents |docfilter:query:categories on init
2) d of filteredDocuments which is a repeat over the filtered at the very beginning array
Assuming you have an outer-element, you can stuff the filtered items into an ad-hoc property like this:
<!-- assign the filtered items to the div's "items" property: -->
<div ref="myDiv" items.bind="documents | docfilter : query : categories">
<!-- use the filtered items: -->
<div repeat.for="d of myDiv.items">
<doc-template d.bind="d"></doc-template>
</div>
</div>
I know this isn't exactly what you're looking for but it will do the job. I'm looking into whether it would be helpfull to add a let binding command- something like this: <div let.foo="some binding expression">
Edit
Here's something a bit nicer:
https://gist.run/?id=1847b233d0bfa14e0c6c4df1d7952597
<template>
<ul with.bind="myArray | filter">
<li repeat.for="item of $this">${item}</li>
</ul>
</template>
I have this fallowing list:
<ul data-template="view" data-bind="source: contacts"></ul>
...
<script type="text/x-kendo-template" id="view">
<li>
<div data-role="button" data-bind="click: viewContact">
<h4>#: first_name #</h4>
</div>
</li>
</script>
var someClass = kendo.observable({
title : 'Contact',
contacts : [],
getContacts: function () {
var data = new Contacts().get();
$.when(data()).then(function (data) {
someClass.contacts = data;
});
}
});
I want to assign data from getContacts to products and populate the template with results as they come in.
Any ideas?
In your question you are talking about "products" but in the code snippet i see "contacts".
In any case, you need to do the following:
someClass.set('contacts', data)
Note: assuming you have contacts as a property on the viewmodel.
Since its an observable object, if you don't use get() & set() methods, kendo wont know who all are observing that property. If you use set() method to set new value, Kendo will propagate the change and will notify the listeners of the property.
I have a page with a form. In this form user can add multiple rows with key and values. There is a restriction that the customFields is created on the fly, not from any subscribed collection.
...html
<template name="main">
{{#each customFields}}
<div>
<input type="text" value="{{key}}"/>
<input type="text" style="width: 300px;" value="{{value}}"/>
</div>
{{/each}}
</template
.... router.js
Router.route 'products.add',
path: '/products/add/:_id'
data:
customFields:[]
....products.js
#using customFieldSet as Reactive Var from meteor package
Template.product.created = ->
#customFieldSet = new ReactiveVar([])
Template.product.rendered = ->
self = this
Tracker.autorun ->
arr = self.customFieldSet.get()
self.data.customFields = arr
Template.product.events(
'click .productForm__addField': (e)->
t = Template.instance()
m = t.customFieldSet.get()
console.log t
m.push(
key: ''
value: ''
)
t.customFieldSet.set m
....
The last event will be trigger when I click the button. And it add another row with key and value empty to the page.
Please advise me why I actually see the reactive variable customFieldSet updated, but there is nothing changed dynamically in html.
P/s: I guess customFields is not updated via Iron router.
Basically, you're doing the thing right. However, you shouldn't be assigning the new reactive data to your template's data context, but rather access it directly from your helpers:
Template.product.helpers({
customFileds: function () {
return Template.instance().customFiledsSet.get();
},
});
Now you can use {{customFields}} in your template code and it should work reactively. Just remember that {{this.customFileds}} or {{./customFileds}} will not work in this case.
I just started using knockout.js and it works great with normal bidings. I have a problem with observableArray.
I want to create an observableArray and assign to it a JSON data from Google Feed API. Here is the JSON format https://developers.google.com/feed/v1/devguide#resultJson
google.load("feeds", "1"); // Loads Google Feed API
function FeedViewModel()
{
// Data
var self = this;
self.allEntries = null;
// Example property, and it works
self.feedHead = ko.observable("BBC News");
var feed = new google.feeds.Feed("feeds.feedburner.com/BBCNews");
feed.setResultFormat(google.feeds.Feed.JSON_FORMAT);
feed.includeHistoricalEntries();
feed.setNumEntries(30);
// Loads feed results
feed.load(function (result) {
if (!result.error) {
self.allEntries = ko.observableArray(result.feed.entries);
// accessing the title from here is OK
alert(self.allEntries()[1].title);
}
});
}
In the above example, accessing the array from the ViewModel is OK but I need to display it in the view (to the browser) using foreach:allEntries
<h2 data-bind="text: feedHead">Latest News</h2>
<!-- ko foreach:allEntries -->
<div class="lists">
</div>
<!-- /ko -->
But nothing the ko foreach loop returns nothing. The observable feedHead is OK.
Also I dont have any JS error. Any help..
Try declaring ( where you have the // Data )
self.allEntries = ko.observableArray([]);
then in the load...
self.allEntries(result.feed.entries);