Passing JSON object as parameter from View to Controller function? - extjs

Basically I've a panel called DummyPanel, Now on dummypanel initialize event I've called a controller function like as follows:
var me = component;
var fieldCollection =
{
"Order" : 'ordNumber',
"Ref": 'refNumber'
};
me.fireEvent('myControllerFunction','Param1', fieldCollection, 'Param3');
Now I want to get fieldCollection JSON object value within function myControllerFunction, to get value from fieldCollection I'm using following code:
myControllerFunction(param1, collection, param3)
{
Ext.Msg.alert(collection.Order);
}
But it does not return anything. So please let me know how to resolve this problem!!
Any comment will appreciated!!

I'm not quite sure what it means "But it does not return anything", but I'll try.
So, your "DummyPanel" view have a alias or itemId property. In yor controller (in init() function), you need "keep track" of your view. For example:
In your view:
me.fireEvent('myEventName','Param1', fieldCollection, 'Param3');
In your controller:
init:function(){
var me = this;
this.control({
'panel[itemId=your-view-itemId]': { // call your function after event
myEventName: me.myControllerFunction
}
});
...
},
...
myControllerFunction: function(...) {
...
}

Should it not be
Ext.Msg.alert(collection["Order"])?
Or if you want to keep Ext.Msg.alert the way it is fieldCollection should be defined this way
var fieldCollection =
{
Order : 'ordNumber',
Ref : 'refNumber'
};

Related

angular-dialog-service update parent scope data object

I've a template:
<p class="text-right">
<a ng-click="editTherapeuticProposal(meow.accepted_tp)" class="fa fa-pencil"></a>
</p>
which calls the editTherapeuticProposal function defined in its controller, passing it the meow.accepted_tp object (here I use angular-dialog-service: https://github.com/m-e-conroy/angular-dialog-service):
// here tp is equal to meow.accepted_tp
$scope.editTherapeuticProposal = function(tp) {
dialogs.create('surgeon/templates/create_edit_therapeutic_proposal.tpl.html', 'SurgeonCreateEditTherapeuticProposalCtrl', {scope: $scope, tp: tp}, { copy: false });
};
tp is an object.
Then in the dialog controller I display a form in order to let the user modify tp. I do some stuff, the relevant ones are:
// data is the object received by the dialog controller: {scope: $scope, tp: tp}
if(typeof data.tp != 'undefined') {
$scope.therapeuticProposal = angular.copy(data.tp);
}
I copy the object to work on a different object (I don't want data to be updated if not saved)
When pressing the save button in the dialog, the following function runs:
var complete = function(tp) {
data.tp = tp;
//...
}
Ok, the problem is that meow.accepted_tp in the parent scope doesn't get updated. If I do
var complete = function(tp) {
data.tp.title = 'meow';
//...
}
Its title gets updated. There is clearly something wrong with the prototypal inheritance, I know that in order to get variables updated they should be properties of an object, but tp is already passed as an object property (of the data object). Any ideas?
Edit
After re-reading the angular-dialog-service docs, you can pass a result back using modalInstance. It sounds like this is what you want to do.
The reason your binding isn't working is because you're changing the object reference from a child scope, rather than a property on the object bound (which is why data.tp.title = 'meow' works).
Anyway, for your case, try this:
// here tp is equal to meow.accepted_tp
$scope.editTherapeuticProposal = function(tp) {
var dlg = dialogs.create('surgeon/templates/create_edit_therapeutic_proposal.tpl.html', 'SurgeonCreateEditTherapeuticProposalCtrl', {scope: $scope, data: data}, { copy: false });
dlg.result.then(function(tp) {
// Get the result and update meow.accept_tp
$scope.meow.accepted_tp = tp;
});
};
Then in the dialog, when you complete, do:
var complete = function(tp) {
$modalInstance.close(tp);
}
For an example, see http://codepen.io/m-e-conroy/pen/rkIqv, in particular the customDialogCtrl (not customDialogCtrl2) is what you want.

why behaviors are not allowed to pass dynamically?

I am working on Marionette.behavior.I was trying to pass the behaviors hash dynamically at the time of view initialization but it is not getting assigned to the behaviors object of view.because behaviors are getting initialized at the time of view construction.
so we achieved the solution in the following way but is it the right way to achieve it?
is there any other way to achieve? and
why behaviors are not allowed to pass dynamically?
Here's the code:
var Behaviour = new Marionette.Application();
Behaviour.addRegions({
mainRegion:"#main-region"
});
var Person = Backbone.Model.extend({
defaults:{
firstName:"NA",
lastName:"NA",
phoneNumber:"NA",
presentAddr:"NA",
permanantAddr:"NA"
}
});
var buttonView=Marionette.ItemView.extend({
template:"#buttontemplate",
constructor:function(options){
this.behaviors = options.behaviors;
Marionette.ItemView.apply(this, arguments);
},
events:{
"click .display":"displayDetail"
},
displayDetail:function(){
this.triggerMethod("DisplayPersonDetails");
},
//behaviors:{Behavior1:{ },Behavior2:{ }}
})
var PersonDetailsView = Marionette.ItemView.extend({
template:"#static-template",
ui: {
"Change": ".change"
},
events:{
"click #ui.Change":"changeBehavior"
},
changeBehavior:function(){
},
});
var Behavior1 = Marionette.Behavior.extend({
onDisplayPersonDetails:function(){
var person=new Person({firstName:"abhijeet",lastName:"avhad",phoneNumber:"9604074690",permanantAddr:"sangamner",presentAddr:""})
var myView = new PersonDetailsView({model:person});
Behaviour.mainRegion.show(myView);
}
});
var Behavior2 = Marionette.Behavior.extend({
onDisplayPersonDetails:function(){
var person =new Person({firstName:"abhijeet",lastName:"avhad",phoneNumber:"9604074690",permanantAddr:"",presentAddr:"shivajinagar"})
var myView =new PersonDetailsView({model:person});
Behaviour.mainRegion.show(myView);
}
});
Behaviour.on("initialize:after", function(){
console.log(" started!");
Marionette.Behaviors.behaviorsLookup = function() {
return window.Behaviors;
};
window.Behaviors = {};
window.Behaviors.Behavior1 = Behavior1;
window.Behaviors.Behavior2 = Behavior2;
var buttonview=new buttonView({behaviors:{Behavior1:{ },Behavior2:{}}});
Behaviour.mainRegion.show(buttonview);
});
Behaviour.start();
The other way of achieving that is in your definition declare a function that returns the behaviors supplied at initialization, like this:
var buttonView=Marionette.ItemView.extend({
...
behaviors: function () {
return this.options.behaviors;
},
...
This is because the Marionette applies the behaviors in the constructor:
if (_.isObject(this.behaviors)) {
new Marionette.Behaviors(this);
}
You may try to do the same in your initialize method, but I'm not sure if it will work correctly if you already had some behaviors assigned beforehand.
After hacking through the source, I've come up with the following. It breaks encapsulation, which leads me to believe that there is probably a better way. Nonetheless, until I find it, this is going straight into production.
// Define Behavior.
var Behavior1 = { /* Behavior definition */ }
// Create View like normal.
var view = new ItemView({
behaviors: {
behavior1: { behaviorClass: Behavior1 }
}
});
// Here's the ugly part.
view.undelegateEvents();
view._behaviors = Marionette.Behaviors(subview);
view.delegateEvents();
After you do that, your Behaviors should all work.
Behavior can be passed directly with behaviorClass property within declaration of behaviors:
As seen in the marionette.behaviors docs, for example we have Tooltip behavior, which we want to pass directly and not from global list.
define(['marionette', 'lib/tooltip'], function(Marionette, Tooltip) {
var View = Marionette.ItemView.extend({
behaviors: {
Tooltip: {
behaviorClass: Tooltip, // <-- passing the behavior directly here
message: "hello world"
}
}
});
});

using getStore on view reference does not work

I have defined a controller, and assigned refs in it like this:
refs:
[
{
ref: 'refugeDetails',
selector: 'refugedetails'
}
]
I have created a view with xtype = 'refugedetails', and in a function deleteAdmin in my controller I try to remove a record from the store of this view, like this
deleteAdmin: function(index) {
this.getRefugeDetails().getStore().removeAt(index);
}
But it doesn't work, so I tried to see in the same function if getStore returns something like
var st = this.getRefugeDetails().getStore();
if(st) Ext.Msg.alert('st', 'exists');
else Ext.Msg.alert('st', 'does not');
But I do not get an alert, and in the console I get "TypeError: Object [object global] has no method 'getStore'". Am I doing something wrong here?
You cant get store's object form panel.
you can use below code
var st = Ext.getStore('yourStoreId');
it will return object of store.
you can try this:
var store = Ext.data.StoreManager.lookup("RoleStore");
and the 'RoleStore' is you defined
Ext.define("PRO.store.role.RoleStore", {});

Adding a computed field to every element of an array in an AngularJS model

I'm pulling an array of users into my AngularJS model from a JSON datasource. This data is being rendered in a table, and I'd like to create a column that is computed from two values of the existing user object, without modifying my underlying data service.
// My model
function UserListCtrl($scope,$http) {
$http.get('users').success(function(data) {
$scope.users = data;
});
};
In my partial template, I know I can do something like this:
<tr ng-repeat="for user in users">
<td>{{user.data / user.count | number:2}}</td>
</td>
But I'd rather add that field into the model, so I can use it like so:
<td>{{user.amplification}}</td>
How do I add the "amplification" field to every user in my model?
As an aside, is it possible to use the orderBy filter on something like this:
<td>{{user.data / user.count | number:2}}</td>
You can eather:
Just after loading user do:
$http.get('users').success(function(data) {
$scope.users = data;
$scope.user.amplification() = function() { return $scope.user.data / $scope.user.count; }
});
And use as {{user.amplification()}}
Anywhere at controller:
$scope.$watch('user', function() {
$scope.userAmplification = $scope.user.data / $scope.user.count;
}, true);
$http.get
Or if user.data/count do not change, do same as 1. but staticly calculate:
$http.get('users').success(function(data) {
$scope.users = data;
$scope.user.amplification = $scope.user.data / $scope.user.count;
});
And OrderBy could be used on any expression (uncluding result of other filter)
If you don't need your amplicification() function to update when the data and count properties on your user update, you can do something like this in your controller:
$scope.users.forEach(function(user) {
user.amplification = function() {
return user.data / user.count;
};
});
Adding a second answer as I feel it's appropriate as it's distinct from my first one.
After a little looking around, I found the method I originally posted falls over if you try to add new rows dynamically, or new elements to the array which depend on the computed value. This is because the $scope.array.forEach() will only run when the controller is created.
The best way to solve this problem is to create a properly defined object which contains the options you want. e.g.
function Task(id, name, prop1, prop2) {
this.id = id;
this.name = name;
this.prop1 = prop1;
this.prop2 = prop2;
this.computedProperty = function () {
return this.prop1 + this.prop2;
};
}
This is far more flexible as each new object created will have the new property.
The only downside is that in your ajax success callback, you'll need to pass each of your users into your 'Users()' constructor.
What worked for me was to add a loop and add the property to each item in that loop. I used a property of the controller but I am sure you can use scope the way you are approaching it in the question.
function(result) {
self.list = result;
angular.forEach(self.list, function(item) {
item.hasDate = function() {
return this.TestDate != null;
}.bind(item); // set this context
});
}
Then in my markup I just used it like this.
<div ng-repeat...>
<div ng-show="item.hasDate()">This item has a date.</div>
</div>

How to pass collection inside jeditable function?

I want to edit my collection using jeditable, where modifyCollection is a function associated with the event dblclick. I have the following code:
initialize : function(options) {
view.__super__.initialize.apply(this, arguments);
this.collection = this.options.collection;
this.render();
},
render : function() {
var template = _.template(tpl, {
collectionForTemplate : this.collection ,
});
this.el.html(template);
return this;
},
modifyCollection : function (event){
$('#name').editable(function(value, settings) {
return (value);
}
,
{ onblur: function(value) {
this.modelID=event.target.nameID;
this.collection = this.options.collection;
console.log("This Collection is: " + this.collection); //Shows : undefined
//
this.reset(value);
$(this).html(value);
return (value);
}
});
The idee is to update the model and subsequently, the collection by means of jeditable. The in place editing works fine, but the problem is, I am not able to pass the collection into the function. I want to save all the changes to my collection locally and send them to the server at a later time. What am I doing wrong here?
Moved the comment to a formal answer in case other people find this thread.
The this inside your onblur() function is not pointing to this collection. Try adding var self = this; inside your modifyCollection() function then in your onblur() change this.collection to self.collection like so:
modifyCollection : function (event) {
var self = this; // Added this line
// When working with functions within functions, we need
// to be careful of what this actually points to.
$('#name').editable(function(value, settings) {
return (value);
}, {
onblur: function(value) {
// Since modelID and collection are part of the larger Backbone object,
// we refer to it through the self var we initialized.
self.modelID = event.target.nameID;
self.collection = self.options.collection;
// Self, declared outside of the function refers to the collection
console.log("This Collection is: " + self.collection);
self.reset(value);
// NOTICE: here we use this instead of self...
$(this).html(value); // this correctly refers to the jQuery element $('#name')
return (value);
}
});
});
UPDATE - Foreboding Note on self
#muistooshort makes a good mention that self is actually a property of window so if you don't declare the var self = this; in your code, you'll be referring to a window obj. Can be aggravating if you're not sure why self seems to exist but doesn't seem to work.
Common use of this kind of coding tends to favor using that or _this instead of self. You have been warned. ;-)

Resources