I have 2 APIs which I want to use simultaneously, API1 and API2.
API2 deliver news feeds to API1, while API1 handles all the content in a list form. This means that if any list in API1 is clicked on, it will it will retrieve the the news feeds from API2 using an ID that has been defined.
Who can help me out here? I am stuck. The screenshot of my code is here: http://i1159.photobucket.com/albums/p637/Apulo_Cosmas/2API.jpg
Thanks so much.
Per the Sencha documentation here (under Digging In): http://docs.sencha.com/touch/2-0/#!/guide/first_app
You need to add a listener and a detail panel to your configuration, using this code (reference to contentId is not needed, you just need to pull the description property -- which contains the content -- from the original feed):
detailCard: {
xtype: 'panel',
scrollable: true,
styleHtmlContent: true
},
listeners: {
itemtap: function(nestedList, list, index, element, post) {
this.getDetailCard().setHtml(post.get('description'));
}
}
It might be easier if you manually listen to your list (which is fetched from API 1) itemtap event.
In your controller, there's should be something like:
refs: {
bloglist: 'blog list'
},
control: {
bloglist: {
itemtap: 'fetchAPI2'
}
},
fetchAPI2: function (list,index,target,record){
id = record.get('contentId'); //this is your id for using API2.
Ext.data.JsonP.request({
scope: this,
url: API2_URL,
callbackKey: 'callback',
params: {your params for API2 here},
callback: function(success,result) {
// whatever you want to do here
}
});
}
Related
I am learning ExtJS framework, for experiments I use on front-end side ExtJS and on back-end side JavaEE Spring framework (it is configured like as REST service). So, I start my front-end part on localhost:1841 and back-end part on localhost:8080. Question is:
How I can say to ExtJS.Store that requests need to send to
localhost:8080/** instead of localhost:1841/**?
Sorry for my English!
In ExtJS have singleton you can use this class.
Singleton pattern is a design pattern which restricts instantiation of a class to only one object. This is useful when exactly one object is needed across the system. The Singleton pattern provides a single point of access to a particular instance. Implementation of a singleton pattern must satisfy the single instance and global access principles.
For this "How I can say to ExtJS.Store that requests need to send to localhost:8080/** instead of localhost:1841/**?"
You can use in your app like below code :
Firstly create singletone class
/*
* Create singletone class in your application
* This class you can access in your application anywhere you want within the app.
* Usage:
* commonUtility.getServerUrl();// whatever property you have defined inside of config you can access like this
*/
Ext.define('APPNAME.utils.SingleToneClassName', {
alternateClassName: 'commonUtility',
singleton: true,
config: {
/*
* you can put local or live also or whatever you want.
* for local it will be ip address like this {'http://192.168.30.83:8080/'}
* for live is will be live tomcate host url {http://example.com/}
*/
serverURL: 'http://192.168.30.83:8080/'
},
constructor: function(config) {
var me = this;
me.initConfig(config);
},
});
Create/Define your store
//Your store
Ext.define('APPNAME.store.StoreName', {
extend: 'Ext.data.Store',
fields: ['your fields here'],
storeId: 'storeIdHere',
alias: "store.storeAliasHere",
proxy: {
type: 'ajax',
url: commonUtility.getServerUrl() + 'your Server Method name here', //Based on your server URL acceptance
withCredentials: true,
reader: {
type: 'json',
rootProperty: 'data',
keepRawData: true
}
},
autoLoad: true, //If you need auto load then put true otherwise false
listeners: {
beforeload: function(store, operation, options) {
//If you have token based authenthication then you need to put like below
store.getProxy().setHeaders({
"x-auth-token": 'your token here'
});
//If you have need to pass some parameter in API method then you can pass like below
store.getProxy().extraParams.your_parameter_name = 'value';
}
},
});
//If you want to load your store on some event or any other functions
//then
Ext.getStore('your_storeId_herer').load({
url: commonUtility.getServerUrl() + 'your Server Method name here', //Based on your server URL acceptance
params: {
//If you have need to pass some params in server side then
//you put here like
name: 'value'
}
});
I hope this will help you. for more details you can refer ExtJS6.x Docs
I'm using YouTube's V3 Data API to add a subscription to a channel. This occurs on a Wordpress installation.
I added Google APIs (for oauth) on Wordpress theme functions:
wp_enqueue_script( 'googleapi', 'https://apis.google.com/js/client.js?onload=googleApiClientReady', array(), '1.0.0', true );
I added in the same way the oauth javascript file, which is the first one here: https://developers.google.com/youtube/v3/code_samples/javascript.
Following this guide(https://developers.google.com/youtube/v3/docs/subscriptions/insert (Apps Script)), I extended the OAuth js with the addSubscription method.
Google Client API seems to be loaded and working as it calls correctly googleApiClientReady on the oauth javascript.
So, this is how the subscription is being inserted:
OAUTH JAVASCRIPT
... ... ...
// After the API loads
function handleAPILoaded() {
addSubscription();
}
function addSubscription() {
// Replace this channel ID with the channel ID you want to subscribe to
var channelId = 'this is filled with the channel ID';
var resource = {
snippet: {
resourceId: {
kind: 'youtube#channel',
channelId: channelId
}
}
};
try {
var response = YouTube.Subscriptions.insert(resource, 'snippet');
jQuery('#success').show();
} catch (e) {
if(e.message.match('subscriptionDuplicate')) {
jQuery('#success').show();
} else {
jQuery('#fail').show();
alert("Please send us a mail () with the following: ERROR: " + e.message);
}
}
So, the first error comes with
YouTube.Subscriptions.insert(resource, 'snippet')
It says YouTube is not defined. I replaced it with:
gapi.client.youtube.subscriptions.insert(resource, 'snippet');
And that error went away. When checking response, as the subscription isn't completed, this is what I get
{"wc":1,"hg":{"Ph":null,"hg":{"path":"/youtube/v3/subscriptions","method":"POST","params":{},"headers":{},"body":"snippet","root":"https://www.googleapis.com"},"wc":"auto"}}
So, I would like to know what's happening on that POST request and what's the solution to this.
I can post the full OAuth file, but it's just as in the example, plus that addSubscription method at the end.
Okay, I got it working, the problem was on the POST request. Here is the full method working:
// Subscribes the authorized user to the channel specified
function addSubscription(channelSub) {
var resource = {
part: 'id,snippet',
snippet: {
resourceId: {
kind: 'youtube#channel',
channelId: channelSub
}
}
};
var request = gapi.client.youtube.subscriptions.insert(resource);
request.execute(function (response) {
var result = response.result;
if (result) {
// alert("Subscription completed");
}
} else {
// alert("Subscripion failed");
// ...
}
});
}
Also make sure to load Google Apps API (in fact without it the authorize/login button won't work) and jQuery.
Any chance you can post everything that made this work...all the JS entire auth.js save for your private keys, im working on this exact problem.
Unanswered: store ajax serving multi read requests (best practice question)
Hi, im trying to understand the proper design concept of Store proxies using the Ajax api config and have a question on how this should be done.
suppose i have a store which has a server proxy using the Ext.data.proxy.Ajax class and i have an api with the following:
proxy: {
type: 'ajax',
api: {
read: 'some/something/list.json',
create: 'some/something/insert.json',
update: 'some/something/update.json',
destroy: 'some/something/destroy.json'
}
}
now suppose my read is triggered by a search button and when i have a blank text box and click search it makes a request through the read api to retrieve the list.json. but i want to have another read as part of the same store / api to read individual records say something like this:
read: 'some/something/<field_value>.json'
my proxy read is already assigned to the list.json but i want to allow the same store proxy to be able to read from individual record searches also. granted that i cant have two read statements in my proxy. how would I go about writing this?
help me understand? maybe my server controller has to be able to determine by keyword #PathVariable if path is list i.e .json then call the list db query otherwise if .json then run the individual search query through the db.?? and if so what would be the read: url?
whats the best way to design and build this?
Thanks in advance
If you want to read single record instead of defining proxy in store you should do it in Model and then call load on model itself something like below.
Ext.define('app.model.User', {
{
fields: [
{ name: 'LoginUserId', type: 'string' },
{ name: 'FirstName', type: 'string' },
{ name: 'LastName', type: 'string' }],
proxy:
{
type: 'rest',
url: '/User',
reader:
{
type: 'json',
root: ''
}
}
});
var user = Ext.ModelMgr.getModel('app.model.User');
user.load(123, {
success: function(userObj) {
}
});
I have seen questions slightly related to this, but none that answer my problem. I have set up an Ext.Ajax.request as follows:
var paramsStringVar = 'param1=1¶m2=two¶m3=something¶m4=etc';
Ext.Ajax.request({
url: '/cgi-bin/url.pl',
method:'POST',
params:paramsStringVar,
timeout:120000,
success: function(response, opts){
var objhtml = response.responseText; //content returned from server side
console.log(objhtml);
}
});
This request retrieves the appropriate content from the backend. One parameter is outputType, which can take values {html, excel, csv}. When returning html to display I am able to handle and display it correctly. Now on to the problem...
When I set the outputType parameter to csv or excel, I get back the appropriate content as csv or tsv(excel) as requested. BUT, I don't want the content, I want a prompt to download the file(csv or excel). How can I have the browser auto prompt the user to download the file instead of just retrieving the text content within extjs?
Version 4.07 so I can't use any 4.1 only features
There seems to be no bulletproof solution but there are several approaches I would try:
1) Use an iframe instead of real XHR to POST data to the server, e.g. <form action="/something" target="myiframe"> where myiframe is the name of your hidden iframe. That way your form would use the iframe (not your main window) to submit data to the configured URL. Your server should set response header as application/octet-stream (or some ither MIME type for binary data) so the browser triggers download. Otherwise (if html returned in your case) you can just retrieve iframe's body innerHTML and display it to the user in UI. While using an iframe (or a new window) instead of XHR doesn't sound like the best idea, this solution seems to be the most reliable so far (and with best browser support).
Here is a slightly modified example from Ext.form.Basic docs page:
Ext.create('Ext.form.Panel', {
title: 'Basic Form',
renderTo: Ext.getBody(),
width: 350,
// Any configuration items here will be automatically passed along to
// the Ext.form.Basic instance when it gets created.
// *THIS* makes the form use a standard submit mechanism, not XHR
/**/standardSubmit: true,
// URL to submit to
url: 'save-form.php',
items: [{
fieldLabel: 'Field',
xtype: 'textfield',
name: 'theField'
}],
buttons: [{
text: 'Submit',
handler: function() {
// The getForm() method returns the Ext.form.Basic instance:
var form = this.up('form').getForm();
if (form.isValid()) {
// Submit the Ajax request and handle the response
form.submit({
success: function(form, action) {
Ext.Msg.alert('Success', action.result.msg);
},
failure: function(form, action) {
Ext.Msg.alert('Failed', action.result.msg);
},
// You can put the name of your iframe here instead of _blank
// this parameter makes its way to Ext.form.Basic.doAction()
// and further leads to creation of StandardSubmit action instance
/**/ target: '_blank'
});
}
}
}]
});
There are two key parameters here (lines marked with /**/):
standardSubmit: true config that you pass to your form will make it do a standard submit instead of XHR.
Passing a target parameter to the form's submit action. This feature is not documented but you can see it being used in Ext.form.action.Submit source code (all options that you pass to Ext.form.Basic.submit() method end up as parameters of Ext.form.action.* instance.
In the example code I put target: '_blank' to demonstrate that it works right away (will create a new browser window). You can replace it with the name of your iframe later but I suggest that you first test how your form submits data to a regular new window and then develop logic that creates and processes an iframe. You will have to process the result inside iframe yourself, thought. It's not that difficult, see Ext.data.Connection.upload() implementation as an example of iframe processing.
ExtJS actually already uses the iframe technique for file uploads. See Ext.data.Connection and Ext.form.field.Field.isFileUpload() for an idea of how it can work.
2) Suggested here: Using HTML5/Javascript to generate and save a file.
If you don't want to go the iframe way, you can try generate data URI from response data and navigate to that URI triggering download:
content = "Hello world!";
uriContent = "data:application/octet-stream," + encodeURIComponent(content);
window.location.href = uriContent;
Again, mimetype is essential here. This worked for me, you should note, however, that browsers impose a size limit to data URIs (256Kb is a safe bet).
3) Another answer in the mentioned thread links to FileSaver.js library the implements the (abandoned?) w3 spec. Usage and demo here. It uses [BlobBuilder] to generate a blob of binary data that is further used to initialize downloads using one of several methods. While this solution seems to work, it uses deprecated APIs and may not be future-proof.
Below is my solution. This is how I have it currently working. The response generates a download/open prompt, based on a response type of text/csv. Note that no iFrame or reference to an iframe are needed. I spent a lot of time hung up on the need for an iFrame, which actually broke my solution. An iFrame is not needed to generate a download prompt. What is needed is a request(submittal) similar to this one, along with a backend generating the appropriate csv with text/csv response header.
var hiddenForm = Ext.create('Ext.form.Panel', {
title:'hiddenForm',
standardSubmit: true,
url: /cgi-bin/url.pl
timeout: 120000,
height:0,
width: 0,
hidden:true,
items:[
{xtype:'hiddenField', name:'field1', value:'field1Value'},
// additional fields
]
})
hiddenForm.getForm().submit()
The standardSubmit line is vital
You don't need to create a form panel and make it hidden in your extjs file. We can add a html form and on click of button in extjs file we can submit the form using the url. This will work both in IE as well as chrome browsers. Below is my code i tried and its working fine,
<form action="<%=fullURL%>/DownloadServlet.do" method="get" id="downloadForm" name="downloadForm" target="_self">
</form>
click:
{
fn: function()
{
document.getElementById('downloadForm').submit();
}
}
To get it working on ExtJS 3.4:
var hiddenForm = new Ext.FormPanel({
id:'hiddenForm',
region: 'south',
method: 'POST',
url: "/cgi/test.wsgi",
height: 0,
standardSubmit: true,
hidden:true,
items:[
{xtype:'hidden', name:'p', value:p},
{xtype:'hidden', name:'g', value:g},
// ...
],
});
linkThis = new Ext.Button({
text: 'Download this CSV',
handler: function() {
hiddenForm.getForm().submit();
},
maxHeight: 30,
});
Remember that in order to make it working, you should put the hiddenForm in any container (i.e. in the same Ext.Window of the button), for example:
risultatiWindow = new Ext.Window({
title: 'CSV Export',
height: 400,
width: 500,
....
items: [...., hiddenForm]
});
Ok, I am semi-new to ExtJS, and I am building a program that has "inputs" that are listed in a grid, and in my DB these inputs can be linked to "symptoms".
I am trying to create a function that will take in the id of the input and grab all of the symptoms from the database that are linked to that symptom, and list them in a field set.
It works fine when I click on an input that is only linked to one symptom, but if the input is linked to more than one symptom, then the error says.. "invalid property id"
This is what I have for my function.
function listSymptoms(inputID){
Ext.Ajax.request({
url: "../../inc/project4.php?list=symptoms",
reader: new (Ext.data.JsonReader)({
root: "symptoms",
inputid: "id"
}),
params: {
inputid: inputID
},
method: "POST",
success: function (f, a){
var jsonData = Ext.util.JSON.decode(f.responseText);
symptomsFieldSet.body.update(jsonData.data.name);
},
failure: function (f,a){
Ext.Msg.alert('There was a problem opening your message.');
}
});
}
I have the inputID for the function being passed in when the user clicks on one of the inputs that are held inside the grid.
I believe that my problem has something to do with this line..
symptomsFieldSet.body.update(jsonData.data.name);
I am just stumped on how to handle this. Do I need to create a data store like I have for grids? Or is there an easier way to do this?
ANY help is appreciated! thanks in advance.
I think you need to rethink the structure of your JSON response object. You can send this in your JSON response to your request. If you are using Ext.util.Ajax calls instad of a form, you'll need to decode this JSON response string using the util method Ext.util.JSON.decode(). Check out the API Documentation
{
success: true,
msg: {text: 'this can be used for error message handling' },
data : [
{id:1,
chiefComplaint: 'head hurts',
symptoms: [
{symptomID: '740.1', text: 'Headache'},
{symptomID: '12352135'. text: 'and so on'}
}
]
]
}