Does nativescript use 2 view models - nativescript

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...

Related

Should the store know the view?

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

An aesthetic or correct way of invoking an action that requires DOM manipulation as well as controller related tasks in EmberJS

My EmberJS app has a couple of actions (triggered by buttons) that require a view/DOM manipulation as well as setting a state in the controller, followed by a model update. The way I do this, it does not appeal to my programming aesthetics. It gets the job done, but it doesn't look good :(
Here is a gist of how I do things :
<button {{action 'whatever' target='view'}}></button>
App.MyView = Ember.View.extend({
actions:{
whatever:function(){
var ctrl = this.get('controller');
ctrl.set('property',value); // arbitrary example of setting a controller property through it's view
ctrl.controllerMethod(); // invoking a controller method through the view
**// do some DOM manipulation**
}
}
});
Naturally, I can wrap whatever controller related steps I am performing in the view in a controller method and invoke that method through the view, but IMO that's just equally ugly. The view shouldn't really be invoking a controller method like how I have done. Unfortunately, this specific action requires a DOM manipulation as well as setting some state and performing an action in the controller.
I am not sure what is the recommended way of performing this. Can anyone enlighten ?
I suggest you handle the action from the controller. I noticed you're setting a property. You can use that to signal something to the view and then do the DOM manipulation within the view.
App.MyView = Ember.View.extend({
function () {
**// do some DOM manipulation**
}.observe('controller.property');
});
The way I think about it is that UI 'actions' are mapped to a business event (e.g. addClient instead of click), then as a result of that something happens that could change properties of the model, controller. As a result of those changes the view might need to update directly, ideally through a binding, but sometimes is needed to modify the DOM manually.
as #LukeMelia said in his comment you should really handle the changes in your controller and update your view (if you need to?) via databinding.
so, you would just omitt the target="view" argument from your view helper and Ember will look for the proper action in the nearest controller, bubbling all the way up to the route, and so on.
a simple code snippet (with what you provided in your first post) would look like:
Handlebars Template:
<button {{action someAction}}>Fire!</button>
Ember.Controller:
App.MyController = Ember.ObjectController.extend({
myProperty: 'cool',
printMyCoolness: function () {
console.log("I'm using Ember.js!");
},
actions: {
someAction: function () {
this.set('myProperty', 'set on fire!');
this.printMyCoolness();
}
}
});

Augmentation and hooking into knockout bindng mechanism

This is something I've been trying to do for quite some time. I've managed something, but I am pretty sure there is a better way.
Question
I want to be able to hook into the bindingProvider process to augment the name of the observable with a prefix (or something similar).
So if I have:
<button data-bind="text: label"></button>
I want to be able to intercept the processig of the binding and replace label with myLabel, so it essentially processed as:
<button data-bind="text: myLabel"></button>
and that is based on some data on the ViewModel that is being applied to the node.
Attempts
use preprocessNode and replace the label value with myLabel before KO gets to it
Obviously, I'd like to avoid doing that, especially since myLabel may be used only in some cases - since it's based on dynamic data on the ViewModel.
Also, no bindingContext reference is available, so I am not sure how to get to ViewModel.
Use custom bindingProvider and do some string/$data mash-up in getBindings
Use preprocess and augment the value
This would be the perfect candidate if not for 2 things: I will have to repeat that for all bindings, since the form is ko.bindingHandlers.<name>.preprocess and it doesn't give me bindingContext, so I can't use that ViewModel data :)
Use extenders
The problem with this is that I need that augmentation behaviour to be applied to all observable values, not just specific ones. By default.
Any suggestions?
Thank you.
Example
To further illustrate the requirement - imagine that I have a template that looks like this:
<ul data-bind="foreach: people">
<li>
<span data-bind="text: name"></span>,
<span data-bind="text: age"></span>
</li>
</ul>
Trivial. Now imagine that ViewModel data looks like this:
{
people: [
{name: 'John', age: 30},
{name: 'Dean', age: 40},
{age: 0.2}
]
}
Basically, there are people and some of them are just born and don't have a name yet.
I'd like to be able to return something like 'noname' for those who are nameless and under the age of 1.
I clearly can do it by changing the template, but this is something I do not want to do. The template may be reused for something that prints noname based on gender, rather than age or something similar.
Hope that helps.
An alternative approach that would solve this particular use case is a custom binding which takes the property name as a string and sets the text to the given property using the viewModel parameter to the binding handler.
A binding like that could look like this:
ko.bindingHandlers.customText = {
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var field = ko.unwrap(valueAccessor())
element.innerText = ko.unwrap(viewModel[field]);
}
}
Here's a full jsfiddle example.
You could also do something more sophisticated than a straight property name lookup - you could even pass in a function to the binding which takes the view model as a parameter and returns the relevant data.
So, observable are the way to go, thank you all who suggested it.
Eventually one of my colleagues had an idea that turned out to be a very nifty simple trick (and I was kicking myself for blacking out on this).
The idea is based on creating a label computed for mylabel observable. This would work in most cases, aside from the case when ViewModel already has an unrelated label observable, which will then be overridden by the computed - something that may not be desired.
For the ViewModel observable I want to map to (in the above example myLabel), instead of the original label you create a computed with the name of label (so that template still works as before), but a trick is to add the label observable not to the ViewModel itself, rather to an object that is instantiated with ViewModel as prototype.
Tha way - all the rest of elements to which this ViewModel is applied will use the label value that it has, and for this specific template the new label computed will shadow the "old" one - which is the desired effect.
Basically:
var Context = function() {
// create computed observable `label` for observable `myLabel`
// based on whatever ViewModel data is needed.
};
Context.prototype = ViewModel;
var context = new Context();
ko.applyBindings(context, node);

Backbone JS where to put Application main logic

Using Backbone i'm starting to build an App where i have everything cleanly separated. But now i have the following question. Where should i put the App main logic, in the views or in the model.
For example i have a view and a model, which are binded to a button and when i click that button i have to make
$.ajax(params)
do i put that in the view or the view calls a method with :
this.model.doAction(params)
which do you think is the best approach?
You can define an events property in the view which is of the format {"event selector": "callback"} for eg. {"click .collapse": "collapse"} where collapse would be a function defined as a property of the view. Then write your ajax request code in this callback function.
Also, unless I am missing something, "binding a view and model to a button" doesn't sound correct Backbone way to me. Instead you should think of one instance of model associated with one instance of the view. Whenever an attribute of the the model instance changes, a model change event will be triggered. You can bind a view function to this event so that change in the model is reflected in the view. Here is a quick example
var Book = Backbone.Model.extend({
// ...
});
var BookView = Backbone.View.extend({
initialize: function () {
this.model.bind('change', this.render, this);
},
render: function () {
// here, make changes to the dom as per changes in model
}
});
To associate a model with a view instance, you can pass the it while instantiating a new
view object..
var book = new Book({
title: "A great book"
});
var view = new BookView({model: book});
view.model.set('author', 'AGreatAuthor');
The set function call will fire change event and will result in render function of view
to be called.
Refer to the annotated source of Todos app example for a complete example.

Backbone.js - Binding from one view to another?

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.

Resources