Extjs Load panel content from ajax - extjs

I have an Ext.Panel with a listener set to 'afterrender'. The callback function is a small ajax code which checks an url, grabs it's contents and add it to the panel. Problem is, the content does not get insterted. If I use the same insert code right above the ajax call, it works. Here's my callback function:
Not working:
function afterrenderCallback () {
// This does not work
var logPanel = Ext.getCmp('aP_ServerLogs');
Ext.Ajax.request({
url: AP_ROOT_URL + '/index.php?r=server/logs',
success: function (r) {
logPanel.add({
html: 'dummy html i don\'t care about the response'
});
}
});
}
Working:
function afterrenderCallback () {
// This does work
var logPanel = Ext.getCmp('aP_ServerLogs');
logPanel.add({
html: 'dummy html i don\'t care about the response'
});
}

You might need to call doLayout() on the panel. However check out Ext.Updater:
http://dev.sencha.com/deploy/dev/docs/?class=Ext.Updater
Panels have this automatically such as:
var panel = new Ext.Panel({
});
panel.body.load(...);
panel.body.update(...);

I'd suspect the callback isn't getting called. You could add a failure case with a simple alert call to check it's not going down that path.
However probably better, similar to what #Lloyd said, you should look at the autoLoad config property.

The autoLoad config is what you want, as mentioned. I wanted to add that doing a logPanel.add({...}) just to insert markup is not appropriate, even though it "works". There is no reason to nest a panel within a panel for this. If you are loading HTML content like this you'd preferably do logPanel.body.update('content');.

As #bmoeskau says, the autoLoad config is what we need. It took me quite a while to find the correct syntax though. So here is an example on how to define such a panel with ajax content:
Ext.define('MyApp.view.aP_ServerLogs', {
extend : 'Ext.panel.Panel',
id: 'aP_ServerLogs',
loader: {
url: AP_ROOT_URL + '/index.php?r=server/logs',
autoLoad: true
}
});

Related

ng-click doesn't work with external JavaScript

I am creating an ionic project and I am trying to integrate with Algolia autocomplete.js. I managed to make the search system work, however I added a ng-click on my search results and this function is not working as presented in this codepen that I did as example below:
http://codepen.io/marcos_arata/pen/VKVOky
Inside my algolia's result template:
<a ng-click="add_name({{{ name }}})">
Function that should be run when clicked:
$scope.add_name = function(name) {
alert('User added!');
console.log(name);
}
I tried to inject the results inside the scope but didn't work as well:
autocomplete('#search_name', { hint: false, debug: true, openOnFocus: true },[{
source: index.ttAdapter({ hitsPerPage: 15 }),
templates: {
header: '',
suggestion: function(hit) {
$scope.hit = hit;
return template.render(hit);
}
}
}]);
http://codepen.io/marcos_arata/pen/VKVOky
---- SOLVED ----
Instead of creating a ng-click function inside your templates, you can handle the event click of your search inside your "autocomplete:selected" function and use the dataset and suggestion results.
.on('autocomplete:selected', function(event, suggestion, dataset) {
$scope.name = suggestion.name;
console.log($scope.name);
## create any functions with the suggestion and dataset results inside
});
EDITING THE ANSWER:
Here is the codepen:
Apparently the suggestion keep the name clicked, so you dont need an extra function:
.on('autocomplete:selected', function(event, suggestion, dataset) {
$scope.name = suggestion.name;
console.log($scope.name);
});

Sencha Touch loading from store after login - race issue?

I intend to load data from server only after the user is Authenticated.
For simplicity, let us assume that the user is already authenticated.
I put the load data function call (that loads data from a store) in the Main.js initialize function as you can see below.
However, the getStore('storeId').load() function is async, which makes me worried in case the data store finished loading only after the Main view finished loading which might make the view load without the data (fix me if I am wrong, maybe sencha can deal with this, the view has reference to the storeId).
What is the best practice to target such issues?
Trivial solution: calling the store load synchronously, but does it make any difference? and just in case, how to do it? I tried to add synchronous variable set to true but doesn't work.
app.js
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
Ext.Ajax.request({
url: MyApp.app.baseUrl + 'session/mobileCheckAuth',
method: "POST",
useDefaultXhrHeader: false,
withCredentials: true,
success: function(response, opts) {
if (response && response.status === 200) {
Ext.Viewport.add(Ext.create('MyApp.view.Main'));
} else {
Ext.Viewport.add(Ext.create('MyApp.view.LoginPanel'));
}
},
failure: function(response, opts) {
alert('Unexpected failure detected');
Ext.Viewport.add(Ext.create('MyApp.view.LoginPanel'));
}
});
},
Main.js
Ext.define('MyApp.view.Main', {
...
initialize: function() {
console.log('main.initialize');
this.callParent(arguments);
// Load app data
MyApp.utils.Functions.loadData();
}
There are two ways to solve this :
If your view consists of a grid, there will not be a race condition. If the grid renders before the store has finished loading, the grid will update itself with the new data that is added. For this to work, you have to declare the store as 'store: "mystore";' .
If you have a complex view that is not directly bound to the store, you have to load the store first, and in the on 'load' event of the store you initialize the rendering of the view.
store.load({callback: function(){
Ext.Viewport.add(Ext.create('MyApp.view.Main'}
});

What would keep setter methods from being created in sencha touch

I have a simple controller that I'm starting to build in sencha touch 2:
Ext.define('ScoreKeeper.controller.GameScores', {
extend: 'Ext.app.Controller',
config: {
refs: {
requestButton: 'button[name=RequestButton]',
responseArea: '#scoreResponse'
},
control: {
requestButton: {
tap: 'sendRequest'
}
}
},
sendRequest: function (){
Ext.Ajax.request({
url: 'message',
method: 'GET',
disableCaching: false,
scope: this,
callback: function(options, success, response) {
this.setResponse(response.responseText);
}
});
},
setResponse: function (responseText){
this.setResponseArea(responseText);
}
});
When I tap my requestButton the sendRequest method fires correctly but when it gets to the setResponse method, it fails on the this.setResponseArea step.
When I checked my browser dev tools, it looks like the getter methods for both of my refs get created, but neither of the setter methods do.
What would keep these methods from being created?
Assuming #responseArea refers to an HTML element like a <div>. To attribute the response from your server to the HTML element, do this:
this.getResponseArea.setHtml(responseText);
instead of
this.setResponseArea(responseText);.
Don't forget getResponseArea gets you the HTML element with #responseArea as id. When you got it, you can do whatever you want with it; for example:
this.getResponseArea.setValue(responseText);
or
this.getResponseArea.getValue();.
That's why there is a get but no set.

Backbone.js - Liking a post, code refactoring

Right now I'm using this code to Like a post. I'm Using jQuery methods to change the Like to Unlike and to change the Like count
View
Streaming.Views.StreamsIndex = Backbone.View.extend({
events: {
'click .like-icon': 'post_liked',
},
initialize: function(){
this.model = new Streaming.Models.StreamsIndex();
this.model.bind('post_likeSuccess', this.post_likeSuccess);
},
post_liked: function(event) {
event.preventDefault();
event.stopPropagation();
current_target = $(event.currentTarget);
liked_id = current_target.attr("id");
href = current_target.attr('href');
this.model.like(href, liked_id); // calls model to send API call for Like
},
post_likeSuccess: function(data, liked_id) {
$("#" + liked_id).attr({
"href": data.unlike,
"title": "Unlike",
"rel": "Unlike",
"class": "likehead-ico_active" // changing like icon
});
//changing like count
$("#"+ liked_id+"_count").text(parseInt($("#"+ liked_id+"_count").text()) + 1);
}
});
Model:
Streaming.Models.StreamsIndex = Backbone.Model.extend({
like: function(href, liked_id) {
var self = this;
$.ajax({
url: href,
type: "POST",
dataType: "json",
async: false,
success: function (data) {
self.trigger('post_likeSuccess', data, liked_id);
},
error: function (data) {
self.trigger('post_likeFail', data, liked_id);
alert("This action was not performed");
}
});
}
});
Is there a better way I can do this?
After liking a post can I change the Like text to unLike, Change the like count in a better way without using jquery?
There are several issues with this code. I'll try address them one by one.
Looks like your Streaming.Views.StreamsIndex has several posts in it. It should be broken down into a component views, that are rendered through a collection, so that each model in the collection is bound to a view. You could, maybe call it Streaming.Views.StreamPost
Your initialize method would have:
this.collection = this.model.posts(); // Or something to this effect
Your render method would have:
// addPost is a function
// that takes 'post' as a parameter
// build the corresponding view object
// and appends it to the posts container
this.collection.each(this.addPost, this)
// example of how addPost looks
var view = new Streaming.Views.StreamPost({model: post});
this.$('#posts-container').append(view.render().el);
The event listener 'click .like-icon': 'post_liked' should on the new component view Streaming.Views.StreamsIndex, instantiated in the addPost above. With this, you don't have to use the ugly current_target = $(event.currentTarget) hack. You always do this.model.get('id') to get the id of the post. The thumb rule he is to not use jQuery or any other form of raw DOM manipulation when using Backbone. That is what views & templates are for! Adjust your template by putting a little logic (as little as possible) to show something if post is liked, and show something else if post is not liked yet. The job of deciding whether a post is liked or not, is to be done by the Post model. I usually write wrapper methods in views that call relevant methods on the model.
Instead of using custom events like post_likeSuccess, update the state of your model and re-render your view. If you updated your templates like I mentioned above, then re-render would take care of all the DOM manipulation you are doing.

CakePHP and AJAX to update Database without page refresh

I'm working with CakePHP 1.3.7 and I'm trying to do the following:
On a given page, the user can click a link (or image, or button, doesn't matter) that passes a parameter which is saved into a database. BUT, all this, without refreshing the page.
I've been doing some research and I believe I need to use AJAX as well to acomplish this. However, I can't find the a good example/explanation on how to do it.
I think that the idea is to create the link using AJAX, which calls the controller/action that would receive the variable as a parameter and performs the operation to save it in its corresponding field/table of the DB.
Does anyone have a small example of what I want to do? Or maybe point me to some tutorial that explains it... Thanks so much in advance!
EDIT
Well, thank you guys for your replies. THey're not working directly, but I think I'm getting closer to what I want. Here's what i'm doing now:
I have this code in my view:
<div id="prev"><a>click me</a></div>
<div id="message_board"> </div>
I call this JS file:
$(document).ready(function () {
$("#prev").click(function(event) {
$.ajax({data:{name:"John",id:"100"}, dataType:"html", success:function (data, textStatus) {$("#message_board").html(data);}, type:"post", url:"\/galleries\/add"});
return false;
});
});
And my add action in my galleries controller looks like:
function add() {
$this->autoRender = false;
if($this->RequestHandler->isAjax()) {
echo "<h2>Hello</h2>";
print_r($this->data);
$this->layout = 'ajax';
if(!empty($this->data)) {
$fields = array('phone' => 8, 'modified' => false);
$this->User->id = 6;
$this->User->save($fields, false, array('phone'));
}
}
}
When clicking on the '#prev' element, I get a response from the add action, I know because the text 'Hello' is printed inside #message_board. And it does this without refreshing the page, which is why I need. My problem is that I can't make the $.ajax() function to send any data, when it gets to the controller the $this->data is empty, so it never goes inside the if that saves the info to the database (right now it's saving just an easy thing, but I will want it to save the data that comes from the view).
Can anyone see what am I doing wrong? How can I send the data to the controller?
CakePHP does not matter, most of the code you would need for this would be at clientside. Implementing AJAX by yourself is a pain in the $, so you really want to use a library; currently the most popular is probably jQuery. There's a bunch of examples on their AJAX page: http://api.jquery.com/jQuery.ajax/
So, assuming you have something like this in the document:
<form id="s">
<input id="q"/>
<input type="submit" href="Search!"/>
</form>
<div id="r"/>
you can put this in the JavaScript:
$('#s').submit(function(evt) {
evt.preventDefault();
$.ajax({
url: 'foo.php',
data: {
query: $('#q').val()
},
success: function(data) {
$('#r').html(data);
}
});
return false;
});
Then your foo.php only needs to return the fragment HTML that would go into the div#r.
EDIT: I forgot to stop the submit :( Thanks to #Leo for the correction.
EDIT: I can see what your confusion is about. You will not get a data. I haven't worked with CakePHP, but I assume $this->data is what you'd get from $_REQUEST['data']? You don't get that on the server. data is a hash of what is getting submitted; you will directly get the $_REQUEST['name'] and $_REQUEST['id'] (which, I assume, translate into CakePHP as $this->name and $this->id).
You need to add
$('#s').submit(function(evt) {
evt.preventDefault();
To prevent a page refresh, as in Amadans answer just refer to your controller/ action in the url variable
$('#s').submit(function(evt) {
$.ajax({
url: '/patients/search/',
data: {
query: $('#q').val()
},
success: function(data) {
$('#r').html(data);
}
In the patients/add controller action make sure you return a valid result ( in json is good )

Resources