I have a store and I need to add some headers to its proxy. I don't want to use defaultHeaders of the Ext.Ajax singleton as these are specific only to a few stores.
The headers use key / value pairs and the value comes from a variable that is NOT loaded when the store is initially loaded, the variable is populated after a successful login.
For this reason I couldn't use a constructor on the proxy or store as the variable I use for value of a header isn't available.
The only way I could get it to work was using the beforeLoad of store. Is this really the best way of achieving this ?
Here's my listener on my store, I am checking if undefined as it's fired every single time.
listeners: {
beforeload: function( store, operation, eOpts ) {
if (this.proxy.headers === undefined) {
this.proxy.headers = {
'X-GType': CompA.Items.getGtype().get('type'),
Does anyone know a better way ?
There doesn't seem to be an event that fires only once.
As a general answer to the problem of "events only firing once" - you can configure your listener to automatically unlisten after one event.
listeners: {
'beforeload': {
fn: function(...),
single: true
}
}
In general it will be better if you create your view after the 'critical' store is loaded. Meaning that you should most likely need to set autoCreateViewport to false in your application main file. Then manually create it in the store success call back. Hook in the init() method to do that.
Example: (pseudo code)
App.js
init: function() {
myImportantStore.load({
success: function() {
// create your viewport
}
});
}
Related
I am trying to store the settings into the global variable.
var settings= {};
function on_ready() {
Ext.Ajax.request({
url: baseURL,
success: function(response) {
settings = Ext.decode(response.responseText);
},
failure: function(response) {
console.log('server-side failure with status code ' + response.status);
}
});
}
console.log(settings);
The last line of code shows empty. I know that this is asynchronous call and thus it does not work. But don't know the solution. Is there a way how can I do this? I need to use this ˙settings˙ variable throughout my application. That's why it has to be global.
One approach we have used in the past for initializing settings before app start was using server-side templating for the html file. It did nothing more, but simply add a <script> block, and populated it with lines like window['prefix_propname'] = 'propvalue';. Not the most elegant way, but it worked fine.
But first, I'd rethink if you truly need it to be global. It's likely that you could simply have a data field in main's viewmodel with the settings (which are loaded on init of the main's controller), and then bind setting's parts as needed to the children via their config. Logic depending on the settings value then would be either in child's config update / apply methods, expressed via formulas with the settings as one of the parameters, or via a bind (inside view or controller). The bindings inside controller is a very handy feature, which comes up fairly often in my use, and it abstracts away the annoyance of having to deal with async loading; e.g.:
// view controller
init: function() {
var vm = this.getViewModel();
vm.bind('{settings}', function(settings) {
//do your thing here
});
}
All you need is a extjs singleton. Get the instance of singleton inside the success function and assign your settings to that singleton. Also there is an easier way to add singleton, i.e by adding settings in your window object.
success: function(response) {
window["settings"] = Ext.decode(response.responseText);
}
Now you should be able to access the settings globally across the application.Still console.log will not have actual value because the will be other thread created for ajax call the present exection will continue without waiting for success function. You type "settings" after execution of "success" you'll see the contents.
I am using AngularJs 2 and i am having difficulties watching an object.
I have an object like the following in a directive:
scope.timelineFilter = {hasCapacity: true, onlyActivated: true, companyIdList: []};
I have 2 JQuery functions who change certain values of the object (Soon implementing the third)
$("[name='hasCapacity']").bootstrapSwitch().on('switchChange.bootstrapSwitch', function(event, state) {
scope.timelineFilter.hasCapacity = state;
});
$("[name='activeOnly']").bootstrapSwitch().on('switchChange.bootstrapSwitch', function(event, state) {
scope.timelineFilter.onlyActivated = state;
});
These functions work correctly. If i log the scope.timelineFilter after changing it, i can see the change from true to false (or the other way around)
Now i want to do a call to the backend each time this object changes. So i tried implementing a watcher like this:
scope.$watchCollection('timelineFilter', function() {
console.log("Changed");
}, true);
I did set the third parameter to true for reference checking.
The problem is, this event only fires when the page is loaded but when changing the properties, it does never fire anymore.
Also tried without the third parameter, using scope.$watch with and without the third parameter. Same result.
I searched SO, most people tried to watch arrays with objects, so that isn't viable for me as the backend expects an object.
How can i solve this problem? Is the problem in JQuery? By changing it in the JQuery method it does not register for the watcher?
Thanks!
You are doing things outside of angular's digest cycle. You have to invoke it yourself:
$("[name='hasCapacity']").bootstrapSwitch().on('switchChange.bootstrapSwitch', function(event, state) {
scope.timelineFilter.hasCapacity = state;
scope.$digest();
});
$("[name='activeOnly']").bootstrapSwitch().on('switchChange.bootstrapSwitch', function(event, state) {
scope.timelineFilter.onlyActivated = state;
scope.$digest();
});
I curious if there is any agreed upon pattern to check if data has been already loaded before hitting the server.
Say I have my action that looks like this:
Actions.loadRequest.preEmit = function () {
$.get('/store/', function (data) {
Actions.loadSuccess(data);
}.bind(this));
}
This is called from a component that is simply saying give me this data:
But I don't want to hit the server if that data is already in the store.
Should I store the logic of checking the store in the component:
render: function () {
var data = this.state.store.data;
if (!data) {
Actions.loadRequest();
}
Is there a better way to go about this?
In my project I use shouldEmit for this (see https://github.com/reflux/refluxjs#action-hooks). An example from my code:
var streamStore = Reflux.createStore({
[...]
});
actions.loadStream.shouldEmit = function(streamId) {
if(streamId in streamStore.data)
return false;
return true;
};
This lives in the same file as the store definition. I think this is conceptually the right approach because the store saves the data, so the store should be responsible for intercepting the request to load more data and saying not to, just as it's responsible for listening to the action saying more data is available and updating itself.
Unfortunately this won't work with your example because you bound the AJAX call to preEmit, which gets called before shouldEmit. I would suggest refactoring to make the API call in a normal listen call, like this:
Actions.loadRequest.listen(function () {
$.get('/store/', function (data) {
Actions.loadSuccess(data);
}.bind(this));
});
This saves preEmit for the rare case of needing to rewrite an action's arguments before emitting it. I do use this pattern in my code, for example when loading a second page of results, which relies on a next token that came with the first page and is thus in the store. But in the general simple case of "action triggered, so make a request", using listen makes more sense because then you can add preEmit and shouldEmit for more advanced behavior, like the caching you want.
Reflux also has a helper function, listenAndPromise, which further simplifies the common use case of "action fired, make AJAX call, then fire another action when it's done". Your example could become:
Actions.loadRequest.listenAndPromise(function () {
return $.get('/store/');
});
See this section of the docs for more info on how to set that up: https://github.com/reflux/refluxjs#asynchronous-actions
I recently found this great component -> Knockout-Kendo.js.
I use it to handle some behaviors with kendoComboBox.
The synchronization with the viewmodel works perfectly.
I want to listen changes of the control to execute some actions based on the current selected value.
I don't see any property that I can bind in the 'data-bind' attribute to listen changes but I know that internally, the knockout-kendo component listen changes and this is how the viewmodel is able to by sync with the control.
If I try to listen the valueChange event of the control, the problem is my eventhandler is catched before the viewmodel and while running in my eventhandler, I just have the previous value of the control using the viewmodel.
Look at this binding configuration in the component. What I understand is I'm able to use 'enabled', 'search', 'data', 'value' and any other exposed properties of the telerik control. What would be nice would be to define in data-bind attribute a property 'change' with an eventhandler linked in my viewmodel and be sure my eventhandler would be called after the internal eventhandler of the knockout-kendo component.
createBinding({
name: "kendoAutoComplete",
events: {
change: VALUE,
open: {
writeTo: ISOPEN,
value: true
},
close: {
writeTo: ISOPEN,
value: false
}
},
watch: {
enabled: ENABLE,
search: [SEARCH, CLOSE],
data: function(value) {
ko.kendo.setDataSource(this, value);
},
value: VALUE
}
});
I know I can try to modify the order of bind of events to be sure my eventhandler must be called after the synchronization of the viewmodel but I think it's a very bad practice.
Anybody have an idea how I can solve this problem with elegance?
You haven't mentioned why you want to do this. I can imagine two reasons:
To trigger some UI behavior/logic directly;
To trigger business logic (which may in turn trigger UI changes of course);
For people landing at this question with the latter case, here's an alternative solution. (This answer may not be a straight up answer to the OP's question, but seems useful enough to post it here.)
Suppose you have this basic view model:
var ViewModel = function() {
var self = this;
self.kendoObservable = ko.observable("Some text")
};
There are two ways you can indirectly respond to changes by Kendo. First, for simple cases, there's computed observables:
// Option 1, add this to ViewModel
self.dependentObservable = ko.computed(function() {
return self.kendoObservable() === "" ? "Empty" : "Not empty"; // example
});
This dependentObservable will be modified each time the kendoObservable changes. Basic stuff.
If you want to do something more complex when kendoObservable changes, e.g. do an AJAX call or whatnot, you may need a manual subscription:
// Option 2, add this to ViewModel
self.kendoObservable.subscribe(function(newValue) {
// Possibly do an AJAX call here or whatnot. Example:
alert("The new value is: " + newValue);
});
This will allow you to fire some complex logic each time the kendoObservable changes. AFAIK you need to check yourself whether the newValue is actually a changed value, at least in some versions of KO.
For the listeners part of this data store in sencha touch, what exactly does the 'load' event mean? I searched the api documentation but was unable to find an explanation in the data store section nor the observable class section.
new Ext.data.Store({
model: "",
proxy: {
type: "ajax",
url : "/search/json/",
reader: {
type: "json",
root: "searchResult"
}
},
listeners: {
load: myapp.results //Note: myapp.results is a function defined elsewhere
}
});
As an additional note, if anyone knows of a reference which lists all of the listener 'eventnames' such as load, and their significance I would be grateful if they would be so kind as to post them here. (The sencha documentation only says: 'The name of the event to listen for. May also be an object who's property names are event names. See' and ends at See )
Sencha API says "Fires whenever the store reads data from a remote data source." There is all different event-names too. Am I missing something?
This event is fired when the data is loaded.
You must assign a function to use it.
listeners:{
load:function(store,records,options){
// Do stuff, you can access here to the loaded store, the loaded records and options
}
}
It will be called each time the data is loaded, on refresh, on page change, etc.
Consider two components that is one is dependent upon another component which is to used as input by it in such a case we can make use of load function.