I am challenged to understand why it is not possible to push/append items to the observable.fromObject so as to update the view. This is odd to me but im probably missing something.
I am populating this:
//declare the viewmodel
const viewModel = new observableModule.fromObject({
//declare the properties of this viewmodel
bulletins: []
});
with this json:
{"total_bulls":"664","GenericName":"Tocilizumab","brandName":"Actemra","drugCat":"(IL-6) Receptor Antagonist","bullID":4847,"fastURL":"https:\/\/gotopills.com\/?post_type=drug-bulletin&p=4847","litAlertLvl":"High"}
It appears there is no way to add a new item using a push or set and instead it seems that the suggestion is to use the observableArray although i then lose the ability to auto-update the view :(
It seems that the odd way to do this is to drop the observableArray into the observable.fromObject as in:
viewModel.bulletins = new ObservableArray(r);
then do a push on the array:
viewModel.bulletins.push(element);
Maybe there is a better way?
Related
In the image of this project which is the view model file? I would have thought main-page.js but then main-view-model.js is titled "-view-model".
"view-model file" is not really a set programming concept. But I guess you mean a file which only holds one function which acts as a view-model. If that's the case, then main-view-model.js is most probably the "view-model file". Looking at the content it looks view-model-ish.
However 1, you need to look at main-page.js to see how that is used.
However 2, in NativeScript, view models are often observable objects and looking at this code, the ViewModelItem is not an observable object.
not sure about that ViewModelItem object, but in NativeScript, view1.xml is the view and view1.js would be the "code-behind" and that means you will code the logic directly related to the view itself: Button has a tap="getName"? that function goes to view1.js...
viewModel files would be where you create observables with the datas you fetch from a remote source for exemple, and all the methods say 'saveName(ppl)' that would POST your object to the server would be in the viewModel file...
you would create your observable like this:
var studentList = new StudentListViewModel([]);
var pageData = observableModule.fromObject({
studentList: studentList,
student: "",
prof: "Choisir"
});
and any changes has to be set like that:
pageData.set("prof", prof)
hope it is clear...
Actually I am playing around with sencha touch. Sometimes my stores need to know my views. For example:
Ext.define('Ext.Panel', {
id : 'myId',
config : {
padding: 5,
fullscreen : true
},
moo : null
});
Ext.define('Ext.data.Store', {
fetchSomething : function() {
// Fetch stuff and set moo of view like this:
Ext.getCmp('#myid').moo = 'fetched Data';
}
});
This is a general question.
Is it allowed that the store can set properties of the view?
I think yes, because in a store, if you work with templates and load data, in callback method you can say view.setData(fetchedData).
And is the store a controller or model? Because sometimes I get data from
server and have to change the structure so the view can make it visible.
For example I get an array and make from it a map.
According to best practices, no, absolutely not!!
The sencha touch data system allows views to automatically update themselves when the content of a store changes. You need to use dataviews or the record config along with the tpl config of a view to wire this all up.
I wrote (quite an extensive) post about this for beginners on my blog a while back that will really help you with this (I hope!)
http://senchatouchdev.com/wordpress/2014/01/03/an-overview-of-sencha-touch-2s-data-system/
In brief:
Model = a description of a type of data your app will handle
Record = instance of model
Store = collection of records
View = something displayed on screen
Controller = collection of references/methods that wire your app together
I'm working on a Kendo Mobile project with a number of:
Kendo Views (external to root html)
Modal Views (in the root html).
The external files load on demand and everything works fine. But i'd like to have the same load on demand behavior for some of the modal views, because the root/based html file is becoming too large and not manageable.
Is there a way to either:
Store a modal view in an external file? If so is it possible to load via javascript syntax (app.navigate()) rather than the declarative syntax (href='externalmodal').
Manually pre-load an external view without navigating to it first.
This code lets you manually create a view:
var viewUrl = 'blahblahblah';
var element = $.parseHTML('<div data-role=view>test</div>')[0];
element.style.display = 'none';
$(document.body).append(element);
var options = $.extend({}, kendo.parseOptions(element, kendo.mobile.ui.View.fn.options));
var view = new kendo.mobile.ui.View(element, options);
view.element[0].setAttribute('data-url', viewUrl);
kendo.mobile.application.navigate(viewUrl, '');
Depending on what features you use, you may need to instead use code similar that that used for ModalView below so that Kendo creates the subclass (changes: substitute View for ModalView, substitute view for modalview, add data-url, remove call to show(), maybe check that view not already created by checking for element with matching data-url). We haven't tested setting roles.view this way, but we did something similar while testing this stuff out and it worked.
Don't try settings the options - Kendo got confused (at least trying to set useNativeScrolling didn't work, also don't try setting the options object on the subclass unless you really know what you are doing).
Caveat: This was using browserHistory:false (which disables routing) when the kendo.mobile.Application was created. The technique should still work when using browser history if you use a valid url fragment (same as would be created by Kendo for the pushstate/hashchange url).
This is a also way to cleanly subclass kendo.mobile.ui.View that works well - although you must still use data-role=view even though your subclass is a "different" component. Note that you can't just use you cant use your own subclassed component with its own name like role=myview to subclass a view because there are hard-coded checks specifically for data-role=view in the kendo codebase. Same if you wish to subclass: layout modalview drawer splitview page (amongst other hard-coded kendo ui component names - search kendo code for kendo.roleSelector - ugly). e.g.
MyView = kendo.mobile.ui.View.extend({
init: function(element, options) {
kendo.mobile.ui.View.prototype.init.apply(this, arguments);
...
var myView = new MyView('<div data-role=view>test</div>');
Why it works: The relevant function in the Kendo source code is _findViewElement which does element = this.container.children("[" + attr("url") + "='" + urlPath + "']"); to see if the view already exists for a url, before creating a new one. A unique init function is always required as it ends up being the constructor function.
If you want to subclass a modalview, you need to do something different due to the way kendo works:
var MyModalView = kendo.mobile.ui.ModalView.extend({
html: '<div data-role=modalview style="width:90%;display:none;">Foobar</div>',
init: function() {
kendo.mobile.ui.ModalView.prototype.init.apply(this, arguments);
}
});
function makeModalView() {
$(document.body).append($.parseHTML(MyModalView.prototype.html));
var roles = $.extend({}, kendo.mobile.ui.roles);
roles.modalview = MyModalView;
var modalView = kendo.initWidget($(element), {}, roles);
modalView.open();
return modalView;
}
I'm working on Infinite Pagination
(http://addyosmani.github.io/backbone.paginator/examples/infinite-paging/index.html)
I'm using CompositeView for pagination view.
And I've got the following problem. Each time after I get new portions of data Paginator's collection removes old data and adds new so it makes CompositeView to rerender and erase old results.
How can I resolve this problem? I'm thinking about disabling rerender functionality but how it should be done properly?
Thanks in Advance!
var BaseFeedChronoCompositeView = Backbone.Marionette.CompositeView.extend({
tagName: "div",
template: _.template(ChronoFeedComposite_html),
itemView: Article,
events: {
'click #loadmore-button-manual': function (e) {
e.preventDefault();
this.collection.requestNextPage();
},
appendHtml: function (collectionView, itemView, index) {
collectionView.$("#chronoFeed-content").append(itemView.$el);
}
});
Here is the basic code.
this.collection.requestNextPage() - sends request for data to server. After it gets data this.collection removes old models and adds new models.
Composite View is listening for these events and removes itemViews for old models and append itemViews for new models.
And I need CompositeView not to remove old itemViews.
Im not quite sure how this paginator works, as I've never used it. But I think the easiest way to fix this is to make sure that your Collection doesnt remove old models. I assume that when your data is being returned it is doing a set on the collection. If you look at the backbone docs you can see that you can disable this method from removing models http://backbonejs.org/#Collection-set
If you'd like to customize the behavior, you can disable it with
options: {add: false}, {remove: false}, or {merge: false}.
So when you are updating the collection, instead of just calling
myCollection.set([o1,o2,o3]);
you should be doing
myCollection.set([o1,o2,o3], {remove:false});
I have a main app view, with a filter menu in the header. When it's clicked, I want to filter content in a seperate news-feed view. But I don't know how to bind events (and pass class data) from clicks in one view to a function in another.
How can I accomplish this?
There are a number of ways to accomplish this, but probably you want to create a model object, which is shared between the two views. Then on 'click' in view one, update the model object, and bind 'on change' in view two to the model object.
Basically, you can set up both views to stay in sync with the model object, and any changes to the object will result in changes to the view.
Everything in Backbone inherits from Backbone.Events, so you can trigger and bind events from anywhere (docs for Backbone.Events):
var View1 = Backbone.View.extend();
var View2 = Backbone.View.extend({
eventHandler: function(data) {alert(data)}
});
var v1 = new View1;
var v2 = new View2;
v1.bind('hello-world-event', v2.eventHandler)
v1.trigger('hello-world-event', 'Hello World!')
Note that in this example, when v2.eventHandler is called, 'this' will refer to v1. See the backbone docs for more.