I'm writing a sencha touch app using sencha architect. Because my app do lot of ajax request, most of it need to send 'token' in request header for authentication. So I think of create child class base on Ext.Ajax which always has 'token' in request header. Then I can use this child class without care of the header.
MyApp.override.Ajax.request({ ... })
I try define this in app/override/Ajax.js
Ext.define('Myapp.override.Ajax', {
override: 'Ext.Ajax',
headers: {
'token': 'test'
}
});
I also set this as 'requires' in Application. But get error when try to call
Myapp.override.Ajax.request({ ... })
Seem Myapp can not locate .override package (MyApp.override is undifined)
How to let MyApp know override package or what is the correct/best way to do this.
A quick example is very appreciated. Thank you very much.
Update info:
override file location: app\override\Ajax.js
html file:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script>
var Ext = Ext || {};
Ext.theme = {
name: "Default"
};
</script>
<script src="sencha-touch-all-debug.js"></script>
<link rel="stylesheet" href="resources/css/sencha-touch.css">
<script src="app/override/Ajax.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body></body>
</html>
app.js file
Ext.Loader.setConfig({
});
Ext.application({
requires: [
'MyApp.override.Ajax'
],
views: [
'ContactDetailView'
],
name: 'MyApp'
...
App can start without error, but when call MyApp.override.Ajax.request : Cannot read property 'Ajax' of undefined , mean MyApp.override is undefined
Update
Here something news, it better but not working yet.
Ext.define('MyApp.Ajax', {
extend: 'Ext.data.Connection',
singleton: true,
request: function( options ) {
this.constructor(options, options.url);
console.log(options);
options.header = {'Token':'mytoken'};
this.callParent( options );
}
});
and error when try MyApp.Ajax.request() . I'm sure that options.url is exist in options by check the log
[ERROR][Ext.data.Connection#request] No URL specified
I add extend from constructor function
constructor : function (config, url)
{
config = config || {};
//config.url = 'google.com';
this.initConfig(config);
this.callParent(config);
},
Error just disappear when I remove comment from config.url = 'google.com'; but it comes that the config.url there is ajax request url but local file url ??? I see from chrome console and network ?
GET file:///C:/MyApp/assets/www/google.com?_dc=1370855149720
Please help. thanks.
Finally, this is work with me
Ext.define('MyApp.Ajax', {
extend: 'Ext.data.Connection',
singleton: true,
request: function( options ) {
options.headers = {
Token: 'mytoken',
};
this.callParent( [options] );
}
});
And this simple do what i want too, great.
Ext.Ajax.on('beforerequest', (function(conn, options, eOpts) {
options.headers = {
Token: 'mytoken',
};
}), this);
You don't seem to agree with yourself about the name of your override class:
Myapp.override.Ajax
Lunex.override.Ajax
Myapp.override.data.proxy.Ajax
Which one is it? Pay attention to this, the Loader won't go easy about it...
Anyway, you seem a bit confused about override and extend.
extend does create a new class from the parent class, with the modifications you've specified. Then you can use the class you defined, like you're trying to do.
override, on the other hand, applies the modification to the existing class. In this case, the class name is only used for the require statement, and by the loader. No actual class is created. So, in your example, the namespace MyApp.override is not defined, hence the error. Nevertheless, whenever you use Ext.Ajax, your custom header should be sent. Provided you're manager to load your file, that is ;p
Now, your case is a bit special because Ext.Ajax is a singleton instance of Ext.data.Connection. See its code, there's not much in there. And while overriding a singleton can make sense, extending from it would be disturbing.
So, what you were probably trying to do is that:
Ext.define('Myapp.Ajax', {
extend: 'Ext.data.Connection',
headers: {
'token': 'test'
}
});
So that you can do:
Myapp.Ajax.request({ ... });
Whether the best choice here is to override or to extend is a tough question. I'm glad you didn't ask it!
Why not using the config 'defaultHeaders' in your extended class? In that way it's always added to your headers.
http://docs-origin.sencha.com/touch/2.4.0/apidocs/#!/api/Ext.data.Connection-cfg-defaultHeaders
From the source of Ext.data.Connection
setupHeaders: function(xhr, options, data, params) {
var me = this,
headers = Ext.apply({}, options.headers || {}, me.getDefaultHeaders() || {}),
contentType = me.getDefaultPostHeader(),
jsonData = options.jsonData,
xmlData = options.xmlData,
key,
header;
Related
I am trying to make an API call and the following errors with Ajax not being a function:
import $ from 'jquery';
const apiCall = function () {
var url = 'https://images.nasa.gov/#/search-results';
var request = {
q: 'sun',
media_type: 'image'
};
var result = $.ajax({
url: url,
dataType: 'json',
data: request,
type: 'GET'
})
.done(function() {
alert(JSON.stringify(result));
})
.fail(function() {
alert('failed');
})
}
module.exports = apiCall;
I am importing the above in another module and calling it on a button click in the react's render() function like:
import apiCall from './../api/apiCall';
class Gallery extends React.Component {
render () {
return (
<section id="gallery" className="g-site-container gallery">
<div className="grid grid--full">
<div className="gallery__intro">
<Button extraClass=""
type="button"
handleButtonClick={apiCall} />
</div>
</div>
</section>
)
}
}
module.exports = Gallery;
Any thoughts with what am I doing wrong?
In my experience, this type of issue is most often because your transpilation is not working as you might expect - or you are transpiling your code while also using jquery (or any other lib) by including it with a CDN link. If this is the case, here's some info that might help you sort it out:
First, check that your transpiler is actually pulling jquery in. Just having it on the page won't necessarily allow this code to work - because when your transpiler operates on:
import $ from 'jquery'
It's going to expect to first load the jquery package from node_modules and then create an internal name for it, such as $_1 which will be used inside your bundle. If you intend to include jquery on the page via CDN, rather than bundling it in this fashion, you need to mark it as external in your webpack or rollup config. If using webpack, it would look something like:
{
entry: '/path/to/your/application.js',
externals: {
'jquery': '$',
}
}
This essentially tells webpack, "when I import from 'jquery', don't look in node_modules - instead, just assume jquery already exists on the page as window.$. Now, webpack won't attempt to include and bundle all of the jquery lib - and instead of creating $_1 it will actually honor what $ is.
If you do intend to load and bundle jquery as part of your build (not recommended, due to the incredible size-bloat it will entail) - I suggest ensuring that it's installed in node_modules. You can do this with:
npm install -S jquery
or, if you're using yarn:
yarn add jquery
Now, your import statement should load the lib correctly when you re-transpile.
First, ensure you're not using jquery-lite as it excludes ajax features.
Btw, it's not recommended to use both exports.module together with ES6's import / export. Try to just use one of them. Not pretty sure, but it may cause some module troubles that hard to understand.
Additionally, based on $.ajax official document, you have to process data in the callback
$.ajax({
url: url,
dataType: 'json',
data: request,
type: 'GET'
})
.done(function(data) {
// Process data provided from callback function
alert(data);
})
.fail(function() {
alert('failed');
})
Personally I do prefer isomorphic-fetch to make ajax call in React application.
I'm using Rails 3.2.16 and require.js ('requirejs-rails' gem).
My app has a module named ExpensesUI (here is a snippet of it):
$(function() {
define('ExpensesUI', ['OperationsUI'], function(operationsUI) {
var expenses = {
operationConsolidatedCheckbox: "#operation_consolidated",
parcelledNoCheckbox: "#operation_parcelled_no",
parcelledYesCheckbox: "#operation_parcelled_yes",
/* more things */
};
}
});
I can use it perfectly in any .js file with:
require(['ExpensesUI'], function(expensesUI) { console.log(expensesUI.parcelledNoCheckbox); });
But when I try the same require call in a .js.erb, I got 'undefined' logged.
It's not possible to use requirejs with *.js.erb files. Just because requirejs get files out of sprockets.
But instead, you can use named modules in *.html.erb views, for instance:
<script>
define('mymodule', function() {
'use strict';
return {
user: <%= #user.to_json.html_safe %>
};
});
</script>
describe('my homepage', function() {
var ptor = protractor.getInstance();
beforeEach(function(){
// ptor.ignoreSynchronization = true;
ptor.get('http://localhost/myApp/home.html');
// ptor.sleep(5000);
})
describe('login', function(){
var email = element.all(protractor.By.id('email'))
, pass = ptor.findElement(protractor.By.id('password'))
, loginBtn = ptor.findElement(protractor.By.css('#login button'))
;
it('should input and login', function(){
// email.then(function(obj){
// console.log('email', obj)
// })
email.sendKeys('josephine#hotmail.com');
pass.sendKeys('shakalakabam');
loginBtn.click();
})
})
});
the above code returns
Error: Error while waiting for Protractor to sync with the page: {}
and I have no idea why this is, ptor load the page correctly, it seem to be the selection of the elements that fails.
TO SSHMSH:
Thanks, your almost right, and gave me the right philosophy, so the key is to ptor.sleep(3000) to have each page wait til ptor is in sync with the project.
I got the same error message (Angular 1.2.13). My tests were kicked off too early and Protractor didn't seem to wait for Angular to load.
It appeared that I had misconfigured the protractor config file. When the ng-app directive is not defined on the BODY-element, but on a descendant, you have to adjust the rootElement property in your protractor config file to the selector that defines your angular root element, for example:
// protractor-conf.js
rootElement: '.my-app',
when your HTML is:
<div ng-app="myApp" class="my-app">
I'm using ChromeDriver and the above error usually occurs for the first test. I've managed to get around it like this:
ptor.ignoreSynchronization = true;
ptor.get(targetUrl);
ptor.wait(
function() {
return ptor.driver.getCurrentUrl().then(
function(url) {
return targetUrl == url;
});
}, 2000, 'It\'s taking too long to load ' + targetUrl + '!'
);
Essentially you are waiting for the current URL of the browser to become what you've asked for and allow 2s for this to happen.
You probably want to switch the ignoreSynchronization = false afterwards, possibly wrapping it in a ptor.wait(...). Just wondering, would uncommenting the ptor.sleep(5000); not help?
EDIT:
After some experience with Promise/Deferred I've realised the correct way of doing this would be:
loginBtn.click().then(function () {
ptor.getCurrentUrl(targetUrl).then(function (newURL){
expect(newURL).toBe(whatItShouldBe);
});
});
Please note that if you are changing the URL (that is, moving away from the current AngularJS activated page to another, implying the AngularJS library needs to reload and init) than, at least in my experience, there's no way of avoiding the ptor.sleep(...) call. The above will only work if you are staying on the same Angular page, but changing the part of URL after the hashtag.
In my case, I encountered the error with the following code:
describe("application", function() {
it("should set the title", function() {
browser.getTitle().then(function(title) {
expect(title).toEqual("Welcome");
});
});
});
Fixed it by doing this:
describe("application", function() {
it("should set the title", function() {
browser.get("#/home").then(function() {
return browser.getTitle();
}).then(function(title) {
expect(title).toEqual("Welcome");
});
});
});
In other words, I was forgetting to navigate to the page I wanted to test, so Protractor was having trouble finding Angular. D'oh!
The rootElement param of the exports.config object defined in your protractor configuration file must match the element containing your ng-app directive. This doesn't have to be uniquely identifying the element -- 'div' suffices if the directive is in a div, as in my case.
From referenceConf.js:
// Selector for the element housing the angular app - this defaults to
// body, but is necessary if ng-app is on a descendant of <body>
rootElement: 'div',
I got started with Protractor by watching the otherwise excellent egghead.io lecture, where he uses a condensed exports.config. Since rootElement defaults to body, there is no hint as to what is wrong with your configuration if you don't start with a copy of the provided reference configuration, and even then the
Error while waiting for Protractor to sync with the page: {}
message doesn't give much of a clue.
I had to switch from doing this:
describe('navigation', function(){
browser.get('');
var navbar = element(by.css('#nav'));
it('should have a link to home in the navbar', function(){
//validate
});
it('should have a link to search in the navbar', function(){
//validate
});
});
to doing this:
describe('navigation', function(){
beforeEach(function(){
browser.get('');
});
var navbar = element(by.css('#nav'));
it('should have a link to home in the navbar', function(){
//validate
});
it('should have a link to search in the navbar', function(){
//validate
});
});
the key diff being:
beforeEach(function(){
browser.get('');
});
hope this may help someone.
I was getting this error:
Failed: Error while waiting for Protractor to sync with the page: "window.angular is undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details"
The solution was to call page.navigateTo() before page.getTitle().
Before:
import { AppPage } from './app.po';
describe('App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should have the correct title', () => {
expect(page.getTitle()).toEqual('...');
})
});
After:
import { AppPage } from './app.po';
describe('App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
page.navigateTo();
});
it('should have the correct title', () => {
expect(page.getTitle()).toEqual('...');
})
});
If you are using
browser.restart()
in your spec some times, it throws the same error.
Try to use
await browser.restart()
I am creating an MVC3 application, with requireJS. In my views I need to convert the Model object into a knockout viewmodel object. So I need to use knockout and knockout.mapping libraries.
My application is designed in the following way,
1). All the script files are categorized into folders
Scripts/app/home/ - contains the scripts for the views in Home controller.
Scripts/lib/ - contains the scripts like jQuery, knockout,knockout.mapping, requirejs etc
2). In the "_Layout.cshtml" I am referencing "require.js" like this.
<script src="#Url.Content("~/Scripts/lib/require.js")" type="text/javascript"></script>
3). To configure the require.js settings I am using a different script file called "common.js" (Scripts/lib/common.js)
require.config(
{
baseUrl: "/Scripts/",
paths:{
jquery: "lib/jquery-2.0.3",
ko: "lib/knockout-2.3.0",
komapping: "lib/knockout.mapping"
}
});
4). This is my index.js file which is in 'Scripts/app/home/"
define(['ko', 'komapping'], function (ko, komapping) {
var person = function () {
var self = this;
self.getPersonViewModel = function (data) {
return ko.mapping.fromJS(data); ;
};
};
return { Person: person };
});
5). This is my "Index" action method in the "Home" controller
public ActionResult Index()
{
var person = new Person
{
Id = 1,
Name = "John",
Addresses = new List<Address>(new[]{new Address{Country = "Country 1", City = "City 1"}})
};
return View(person);
}
6). Finally this is my "Index" view
#model MMS.Web.Models.Person
<script type="text/javascript">
require(["/Scripts/common/common.js"], function () {
require(["app/home/index"], function (indexJS) {
var person = new indexJS.Person();
var vm = person.getPersonViewModel(#Html.Raw(Json.Encode(Model)));
});
});
</script>
The problem which I am facing is when loading the index.js file, I get a script error that the knockout.js cannot be loaded.
Failed to load resource: the server responded with a status of 404 (Not Found) - http:///Scripts/knockout.js
But if I remove the dependency of "komapping" inside the "index.js" file it loads correctly, but then I cannot use the mapping functionality.
I had a look inside these links, but couldn't find a solution,
Knockout.js mapping plugin with require.js and
https://github.com/SteveSanderson/knockout.mapping/issues/57
Your help, suggestions are much appreciated. Thanks!
I had the same issue. The problem is that the knockout.mapping defines a knockout dependency, so you need to satisfy this one when you load the script.
Here is how you should load your mapping stuff
require.config(
{
baseUrl: "/Scripts/",
paths:{
jquery: "lib/jquery-2.0.3",
knockout: "lib/knockout-2.3.0",
komapping: "lib/knockout.mapping"
},
shim: {
komapping: {
deps: ['knockout'],
exports: 'komapping'
}
}
});
Then in my case, I use an index.js file with a requirejs call like the following
requirejs(['jquery', 'knockout', 'komapping'], function($, ko, komapping){
ko.mapping = komapping;
//Do other stuff here
});
i just came across this ajax upload plugin and i wish to use it inside a form as shown in the demo page example 3. For some reason i am not able to make it work. I am not sure what parameters come into the function. For example here is my sample code.
$(document).ready(function(){
var upload = new AjaxUpload('property_i',
{
action: 'submitproperty.php',
autoSubmit: false,
onSubmit : function(file , extension){
return false;
}
});
var upload_data = upload.setData({
'propertytype':'propertytype'
});
});
Now the ID used in the AjaxUpload function should be ID of the or of the Entire form. Also how do i use setData method. Any suggestions or links will be very helpful. Thanks
I got it to work with the following code:
new AjaxUpload('#uploader_button', {
action: 'filename.ashx',
autoSubmit: true,
onSubmit: function(file, ext) {
// --- stuff here
// --- add postdata parameters
this.setData({ id: 1, title: docTitle.val() });
},
onComplete: function(file, response) {
// --- stuff here too
}
});
it doesn't utilize the var but instead adds the custom data params in the onSubmit block. The only other difference is that I haven't wrapped the parameter key in quotes as it seems to serialize correctly. And I'm not using autoSubmit: false , but instead it's true...
The only way I could get this to work with autoSubmit: false is to add this outside any function:
var uploader;
var uploadFile;
then in the AjaxUpload(...
onChange: function(file, response){
uploader = this;
uploadFile = file;
},
then in the function to do the upload:
uploader.setData({session: session});
uploader.submit();
Hope this helps
I'm using uploadify and very useful.
http://www.uploadify.com/