I am using a Worklight adapter to get the RSS Feed from a web site; the adapter gets me the data in XML format, but the problem is I can't display the data in a Dojo LisItem.
These are the JS functions to call the Adapter:
function loadFeedsSuccess(result) {
console.log("Data sucesfully downloaded, HTTP " + result.status);
if(result.invocationResult.Items.length > 0) {
console.log("Server has returned " + result.invocationResult.Items.length + " item(s)"); displayRSSFeed(result.invocationResult.Items);
}
}
function loadFeedsFailure(result) {
console.log("Error while loading RSS feed: " + result.errorMessage);
}
function displayRSSFeed(rawData) {
var store = new dojo.store.Memory({data:rawData, idProperty: "guid"});
require(["dijit/registry"], function(registry){ var newsList = registry.byId("newsList"); dojo.empty("newsList");
store.query(function(news){
var newsItem = dojox.mobile.ListItem({label:news.title}); newsList.addChild(newsItem); });
});
}
function getNewsInit() {
var invocationData = {
adapter: "FeedReader",
procedure: "getStoriesFiltered"
};
var options = {
onSuccess: loadFeedsSuccess,
onFailure: loadFeedsFailure
};
WL.Client.invokeProcedure(invocationData, options);
}
The Browser doesn't diplay the data an shows the following Error:
[/NewsApp/apps/services/api/News/common/query] exception. ReferenceError: dojo is not defined worklight.js:4673
Uncaught ReferenceError: dojo is not defined
Any one have any idea how to fix my Problem?
if you're using Dojo and setting the async configuration property to true, then the dojo namespace is no longer available. This means that you can't use dojo.store.Memory or dojox.mobile.ListItem anymore.
To solve that issue you either have to disable the async function or use AMD to load your modules:
function displayRSSFeed(rawData) {
require([ "dijit/registry", "dojo/store/Memory", "dojox/mobile/ListItem", "dojo/dom-construct" ], function(registry, Memory, ListItem, domConstruct) {
var store = new Memory({data:rawData, idProperty: "guid"});
var newsList = registry.byId("newsList");
domConstruct.empty("newsList");
store.query(function(news){
var newsItem = new ListItem({label:news.title});
newsList.addChild(newsItem);
});
});
}
If it then throws the error:
ReferenceError: require is not defined
Then it means you're load loading the Dojo core at all, make sure you're loading dojo.js.
Related
At the moment I use php to collect data needs to be printed in one pdf and open pdf in new browser tab. The problem is that it generate to much traffic as soon as I've a lot of users and a lot of docs to be printed in a same time. So I'm looking for a way to collect everything in one html, open it in new tab, fill with data from back-end and print it after.
My issue is to initialize VueJS for the new browser tab. I always have the following warning in console:
vue.js:1141 [Vue warn]: Cannot find element: #app
I guess the reason is that VueJS works with SPA. Is there any way to implement my idea?
Here is template for a new tab needs to be opened in a new tab.
<div id="app">
<printing-form v-for="printedForm in printedForms" track-by="id" :printed-form="printedForm"></printing-form>
</div>
<template id="printingForm-template">
Some HTML need to be printed in new tab.
</template>
Below my JS code to init VueJS
var printButton = $('#print-button');
printButton.on('click', function(e) {
e.preventDefault();
printButton.unbind('click');
printButton.css('color', '#008000');
var idNumbers = TopPanel.getArrayOfId();
if (idNumbers == '') {
idNumbers = TopPanel.getIdNumber();
}
var url = window.location.href + '/form';
$.ajax({
url: url,
data: 'id=[' + idNumbers + ']',
success: function(data) {
var newWindow = window.open(url); //Open URL in new tab
var printedIds = $.parseJSON('[' + idNumbers + ']');
printedIds.forEach(function(item, i, arr) {
var printedField = $('#top-row-'+item).find('.table-field-printed');
if (!printedField.hasClass('true-value')) {
printedField.addClass('fa');
printedField.addClass('fa-check');
printedField.addClass('true-value');
}
});
printButton.css('color', '#4f5762');
printButtonInit();
newWindow.onload = function() {
VuePrinting.vueInit(newWindow); //Here I initialize VueJS module
}
},
error: function(xhr, textStatus, errorThrown) {
alert($.parseJSON(xhr.responseText));
printButton.css('color', '#4f5762');
printButtonInit();
},
});
});
}
This separate module for VueJs
var VuePrinting = (function() {
return {
vueInit: function() {
Vue.component('printingForm', {
temlate: newWindow.document.getElementById('printingForm-template')
});
var vm = new Vue({
el: newWindow.document.getElementById('app'),
data: {
printedForms: [
{ obj1 },
{ obj3 },
{ obj3 }
]
}
});
}
}
})();
UPDATE: I've corrected my code after RoyJ comment, so now it works correct. Only one note... template should also be changed from selector to:
newWindow.document.getElementById('printingForm-template')
When you specify a selector for your el, Vue will look in the current document for it. The new tab will not be part of the current document.
Save a reference when you open the tab. Write the HTML into its document. Query the #app out of the document, and use the actual element instead of a selector in your Vue setup:
var vm = new Vue({
el: newWindow.document.getElementById('app')
});
I have a SqlDataAdapter and I want to store it in a JsonStore collection in MobileFirst and Display it in table form. I have tried using Load() method but its not working.
this is my resultSetCollection.js file
;(function () {
WL.JSONStore.init({
resultSet : {
searchFields: {"EMP_NAME":"string","EMP_ID":"integer"}
}
}, {
// password : 'PleaseChangeThisPassword'
})
.then(function () {
return WL.Client.invokeProcedure({
adapter : 'EmployeeList',
procedure : 'getEmployeeLists',
parameters : []
});
})
.then(function (responseFromAdapter) {
alert('responseFromAdapter:' + JSON.stringify(responseFromAdapter.invocationResult.resultSet));
var accessor = WL.JSONStore.get('resultSet');
var data=responseFromAdapter.invocationResult.resultSet;
var changeOptions = {
replaceCriteria : ['EMP_ID', 'EMP_NAME'],
addNew : true,
markDirty : false
};
return accessor.change(data, changeOptions);
})
.then(function (response) {
console.log(response);
//Here I want to retrieve the collection and display it in a table
})
.fail(function (errObj) {
WL.Logger.ctx({pretty: true}).error(errObj);
});
}());
An adapter procedure request from a client application will have a response object in its success and failure callbacks. So lets assume that the request was successfull and data was returned from the backend server.
Lets also assume you have a JSONStore initialized and properly setup with a collection. You then only need to get the collection and add data to it.
The below example takes the full response from an HTTP adapter request and puts it as-is into a collection. You will of course need to create a better setup for your specific scenario...
Note that the code is not optimised and performance or with 100% proper logic. It's just a demonstration flow.
Tested in MobileFirst Platform Foundation 7.0.0.00.
main.js:
var collectionName = 'mydata';
var collections = {
mydata : {
searchFields : {data: 'string'},
}
};
function wlCommonInit(){
WL.JSONStore.init(collections).then(
function() {
var resourceRequest = new WLResourceRequest("/adapters/myadapter/getStories", WLResourceRequest.GET);
resourceRequest.send().then(resourceRequestSuccess, resourceRequestFailure);
}
);
}
function resourceRequestSuccess(response) {
WL.JSONStore.get(collectionName).add(response).then(
function(){
WL.Logger.info("successfully added response to collection");
displayDataFromCollection();
},
function() {
alert("failed adding response to collection");
}
);
}
function resourceRequestFailure() {
alert ("failure");
}
If you then like to fetch the data from the JSONStore and display it in the HTML, you could do something like this:
// get a specific item from the stored response and display it in a table
function displayDataFromCollection() {
WL.JSONStore.get(collectionName).findAll().then(
function(result) {
$("#mytable").append("<tr><td>" + result[0].json.responseJSON.rss.channel.title + "</td></tr>");
},
function() {
alert ("unable to display collection");
}
);
}
The index.html looks like this:
<table id="mytable">
</table>
I am writing a fontend web app using dojo that does a lot of calls to rest endpoints using xhr. I would like to have a place to store configurations for things like endpoint locations and html tag references. I thought I would use an xhr call to a json file to do this, but I am having trouble getting my functions to trigger in the right order/at all. Below is my main js file which has an init() function that I am passing as the callback to my conf initializer ("ebs/conf") module, also below. I have used the Chrome debugger to set breakpoints within my conf.get() method, and it looks as though it never gets called.
Can someone give me some advice please?
Main JS File:
// module requirements
require([ "dojo/dom", "dojo/on", "ebs/prices", "ebs/cart", "ebs/conf",
"dojo/ready" ], function(dom, on, prices, cart, conf, ready) {
ready(function() {
conf.get("/js/config.json", init());
function init(config) {
on(dom.byId("height"), "keyup", function(event) {
prices.calculate(config);
});
on(dom.byId("width"), "keyup", function(event) {
prices.calculate(config);
});
on(dom.byId("qty"), "keyup", function(event) {
prices.calculate(config);
});
on(dom.byId("grills"), "change", function(event) {
prices.calculate(config);
});
cart.putSampleCart();
cart.load(config);
}
});
});
And here is my 'conf' module ("ebs/conf"):
define(["dojo/json", "dojo/request/xhr"], function(json, xhr) {
return {
get : function(file, callback) {
// Create config object from json config file
var config = null;
xhr(file, {
handleAs : "json"
}).then(function(config) {
callback(config);
}, function(error) {
console.error(error);
return error;
});
}
}
});
Your are not passing the function as the callback. You are executing it and passing the result as the second argument.
conf.get("/js/config.json", init());
should be
conf.get("/js/config.json", init);
I'm new to Dojo and having a hard time with the following piece of code. I don't understand why the chartData is empty at the very end. I created this method based on an example on the Dojo site.
The code is the following:
function(xhr, json, arrayUtil, number, Chart, theme) {
var chartData = [];
var def = xhr.get({
url: "cpuusage.json",
handleAs: "json"
});
def.then(function(res){
var data = [];
arrayUtil.forEach(res.chart, function(chart){
data[chart.x] = number.parse(chart.y);
});
chartData = data;
console.info("chartData1: ", chartData);
}, function(err){
console.error("Failed to load JSON data");
});
The first console.info within def.then says that the chartData has the correct value. When I however print the value of chartData after the def.then method finished, it's empty.
How can I make sure that chartData has the same value in and after the def.then call. Many thanks
the, methods in the xhr are all async by nature, but they return a promise. if you want to execute some code after the xhr method it should look like this:
function(xhr, json, arrayUtil, number, Chart, theme) {
var chartData = [];
xhr.get({
url: "cpuusage.json",
handleAs: "json",
load: function(jsonData) {
arrayUtil.forEach(jsonData.chart, function(chart){
chartData[chart.x] = number.parse(chart.y);
});
console.info("JSON loaded from server: ", chartData);
},
error: function() {
console.error("Failed to load JSON data");
}
}).then(function(jsonData){
console.info("chartData: ", chartData);
});
by using the then function of the promise, you make sure your code executes after the AJAX call
I've followed examples for injecting jQuery from the getting started page and that works just fine. I have a local copy of jQuery in the same directory, and do something like...
if(page.injectJs('jquery.min.js')) {
page.evaluate(function(){
//Use jQuery or $
}
}
When I try to inject my own script(s), none of the functions are available to me. Say I have a script called myScript.js that just has
function doSomething() {
// doing something...
}
I cannot then use doSomething like...
if(page.injectJs('myScript.js')) {
console.log('myScript injected... I think');
page.evaluate(function() {
doSomething();
});
} else {
console.log('Failed to inject myScript');
}
I've tried
window.doSomething = function() {};
and
document.doSomething = function() {};
as well with no luck, as well as trying to call them with window.doSomething() or document.doSomething() in the subsequent page.evaluate().
The following works for me, maybe some other part of your app logic is wrong:
inject.coffee
page = require('webpage').create()
page.onConsoleMessage = (msg) -> console.log msg
page.open "http://www.phantomjs.org", (status) ->
if status is "success"
page.includeJs "http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", ->
if page.injectJs "do.js"
page.evaluate ->
title = echoAndReturnTitle('hello')
console.log title
phantom.exit()
do.coffee:
window.echoAndReturnTitle = (arg) ->
console.log "echoing '#{arg}'"
console.log $(".explanation").text()
return document.title
Result:
> phantomjs inject.coffee
echoing 'hello'
PhantomJS is a headless WebKit with JavaScript API.
It has fast and native support for various web standards:
DOM handling, CSS selector, JSON, Canvas, and SVG.
PhantomJS is created by Ariya Hidayat.
PhantomJS: Headless WebKit with JavaScript API
or if you prefer JavaScript (they're auto-generated and a little ugly):
`inject.js':
// Generated by CoffeeScript 1.3.1
(function() {
var page;
page = require('webpage').create();
page.onConsoleMessage = function(msg) {
return console.log(msg);
};
page.open("http://www.phantomjs.org", function(status) {
if (status === "success") {
return page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", function() {
if (page.injectJs("do.js")) {
page.evaluate(function() {
var title;
title = echoAndReturnTitle('hello');
return console.log(title);
});
return phantom.exit();
}
});
}
});
}).call(this);
do.js:
// Generated by CoffeeScript 1.3.1
(function() {
window.echoAndReturnTitle = function(arg) {
console.log("echoing '" + arg + "'");
console.log($(".explanation").text());
return document.title;
};
}).call(this);