How to use server side data in client side-service portal? - servicenow

I have one array called data.list in server side. I am trying to use it in client side by calling like this
c.data.list
When I print it in server side it returns correct data. But in client side it returns undefined.
How can I use that array in client side?
Please give some ideas guys.

So in Servicenow, on the server side code you just refer to data. In the client you then can access data via c.data
Here's an example from my instance;
Server side code;
(function() {
/* populate the 'data' object */
/* e.g., data.table = $sp.getValue('table'); */
var sysId = $sp.getParameter("sys_id");
var spLimit = parseInt(gs.getProperty('glide.service_portal.stream_entry_limit'),10);
var ga = GlideAggregate('sys_journal_field');
ga.addQuery('element_id', sysId);
ga.addAggregate('COUNT');
ga.query();
gs.print(ga.getEncodedQuery());
if (ga.next()) {
var count = parseInt(ga.getAggregate('COUNT'), 10);
data.count = count;
data.exceedsLimit = count > spLimit;
}
})();
HTML;
<div id="show-conversation-limit">
<!--Exceeds limit: {{c.data.exceedsLimit}}
Count: {{c.data.count}}-->
<div ng-if="data.exceedsLimit" class="alert alert-info" role="alert">
Due to the quantity of comments, the some comments have been removed
starting with the oldest.
</div>
</div>

Related

How to submit data to Flask from an Ajax call, and return its response in Flask from another Ajax call?

Sorry if the title is a little confusing. A kind user here on StackOverflow helped me make my Flask app display some scraped data, only now I have added a parameter in the function so that I can scrape the data I want to search for. I have an input box, and I want to be able to get the data from it, and pass it as a string in my python function in Flask
Current HTML Side
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "utf-8">
<title>NBA Data Web App</title>
</head>
<body>
<script src = "http://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" crossorigin = "anonymous"></script>
<form id = "nameForm" method = "POST" role = "form">
<input name = "text">
<button id = "searchBtn"> Search </button>
</form>
<div id = "container"></div>
<script type = "text/javascript">
//Function to take place when our search button is clicked
$('button#searchBtn').click(function() {
$.ajax({
url: '/_get_data',
data: $('form').serialize(),
type: 'POST',
success: function(response) {
console.log = response;
},
error: function() {
alert('Failure in first Ajax call');
}
});
/*Everything below this was working before, as I only made one ajax call when a button was pressed. Now, when I press the button, I want to pass its contents as a string to my scrape_data() function in Flask, and return, and display, its contents as shown below. */
//Declare our list so we can print something, and loop through it later
var data_list;
//Variable for our HTML table
var rowMax = 29, html = "<table><tr>";
//Post request
$.post('/_get_data', {
//If done, do this
}).done(function(response) {
/* Assign our scraped data to our variable that was declared earlier,
which is turned into an array here in JS */
data_list = response['data'];
//Declare some variables for making our table
var perRow = 1, count = 0, table = document.createElement("table"),
row = table.insertRow();
//Loop through the data and add it to the cells
for (var i of data_list) {
//Insert a cell for each piece of data
var cell = row.insertCell();
//Add the data to the cell
cell.innerHTML = i;
//Increment our count variable
count++;
//If we have met our set number of items in the row
if (count % perRow == 0) {
//Start a new row
row = table.insertRow();
}
}
//Add the table to our container in our HTML
document.getElementById("container").appendChild(table);
//If request fails
}).fail(function() {
alert("request failed");
});
});
</script>
</body>
</html>
Python (Flask) Side
rom flask import Flask, render_template, jsonify, request, escape, url_for
#Get our lists to post
headers = data_headers()
#Start the flask app
app = Flask(__name__)
#Start page
#app.route('/')
def index():
return render_template('index.html')
#What happens when our button is clicked
#app.route('/_get_data', methods = ['POST'])
def _get_data():
text = request.form['text']
#Here, I am trying to assign the contents of the input box of the form to a variable, so I can pass that variable as a parameter for my function.
data = scrape_data(text)
#Return the json format of the data we scraped
return jsonify({'data' : data})
#Run the app
if __name__ == "__main__":
app.run(debug = True)
I am currently getting error 405 method not allowed. I'm not sure if my syntax in the first Ajax call is incorrect, or if I need to break this up into two different #app.route(urls) since each call is going a different way.
If you use the method attribute of form element and do not specify the action, request will be sent /. What is happening here is when you click on search button it will send two post requests one to '/' and '/_get_data' from ajax. In Flask routing if you do not explicitly provides methods=[] that route will allow GET only. Remove the method attribute from you form, you should not get method not allowed error.

Ordered selection from a dropdown

I want to create an ordered list from a multiple select dropdown list, issue is the select option input provided by html only orders values picked linearly, but I want it ordered according to the order I select them at. So I decided to use some JS to do the trick but wsnt able to hack. Here's the code. Help out please!!
<script language="'javascript'">
function showselection()
{
var frm = document.testing
var opt = frm.testsel
var numofoptions = opt.length
var selValue = new Array
var j = 0
for (i=0; i<numofoptions; i++)
{
if (opt[i].selected === true)
{
selValue[j] = opt[i].value
j++
}
}
selValue = selValue.join("+")
document.getElementById("txtEditions").innerHTML = selValue
}
</script>
<form method=POST name='testing'>
<select name='testsel' multiple onchange='showselection()'>
<option value="one">one</option>
<option value="two">two</option>
<option value="three">three</option>
</select>
<textarea id="txtEditions"></textarea>
</form>
how do i make sure the order of selection is saved and not the order from the source of the dropdown
Codeigniter has a form helper for form_dropdown / form_multiselect this allows you pass an array to the helper function to create the html. you can order the array before parsing it to this function with an array sorting function, like ksort or asort depending on your data.
sorry I can't be of more help because I am not clear exactly what you need to do. if you literally want to save the order, then that means saving it in a database structure in some way.

My Recent Orders on home page, outside of user dashboard

I need to know if I need to create a widget for something like this, or just add a recent orders block to the home page layout.xml.
it should only reflect order for that store.
I know that the user has to be logged in for this to work, but there could be some cookie magic applied to detect the user, and display a short list of recent orders, without displaying the items, which I think is not a massive privacy / security issue.
This is for use in a mobile app, where space is limited, and quick links are helpful...
There will then simply be a link to reorder / view as in the dashboard, and that view would require a descent login.
What is the best way to go about it, if at all possible.
this is a Paypal app, and the recent orders are seen via:
http://www.sitename.com/storename/jsonsales/order/recenttemplate?s=2752732063744
Thanks in Advance.
On top of my head, what I would do is create a custom module with observer to catch when order placed, trigger the process of storing the order in the cookie (e.g. last 3 orders?)
Then just create a block in that module to read the data from the cookie.
After that render that block into the template (either via editing appropriate .phtml or create your own .phtml and add it inside layout.xml).
Hope this helps.
For those that might want to try this, with a module called Paypal order Ahead.
Because this is a paypal specific web app, I was able to do this using the javascript functions calling the json templates.
On the /app/design/frontend/paypal/test/template/cms/index.phtml I added the following:
<div class="content-box greybg recentordercontainer">
<div id="productError_<?php echo $sid; ?>" style="display:none"></div>
<div class="page-title text-title"><?php echo $this->__('My Recent Orders'); ?></div>
<div id="recentorder-list-box_<?php echo $sid; ?>" class=""></div>
<div class="cart-empty" id="cart-empty_<?php echo $sid; ?>" style="display:none">
<div class="box-shadow">
<div class="error-desc cart-row2" style="margin-top:10px;"><?php echo $this->__('You have not yet made any purchases.'); ?></div>
</div>
<div class="pay-now" id="contshop_<?php echo $sid; ?>">
<?php echo Mage::getStoreConfig('checkout/options/continue_shopping_text'); ?>
</div>
</div>
</div>
Then I added some javascript in the script section at the bottom of this template:
getRecentOrderBlockJSON("<?php echo $sid; ?>")
function getRecentOrderBlockJSON(id) {
$.getJSON(storeRootUrl+"/jsonsales/order/recent", function(jsonObj) {
renderRecentOrderBlock(jsonObj,id);
});
}
function renderRecentOrderBlock(jsonObj,id) {
var dataObj = jsonObj.recentorder;
// Recent Order Item box target
var ulObj = $("#recentorder-list-box_"+id);
// Display error message on top
if (jsonObj.messages.error.length >0) {
var pdObj = $("#productError_"+id);
var tplHTML = $("#ErrorPageTemplate").html();
for (key in jsonObj.messages) {
var re = new RegExp("%"+key+"%", "g");
tplHTML = tplHTML.replace(re,jsonObj.messages[key]);
}
pdObj.append(tplHTML);
$("#productError_"+id).css("display","block");
}
// have recent order
if ( dataObj && dataObj.length > 0 ) {
for ( var i=0; i<dataObj.length; i++ ) {
var tplHTML = $("#RecentOrderFrontTemplate").html();
// date
var re = new RegExp("%created_at%", "g");
//tplHTML = tplHTML.replace(re,dataObj[i].order.created_at);
tplHTML = tplHTML.replace(re,dataObj[i].order.created_at_localetime);
// update id
var re3 = new RegExp("%id%", "g");
tplHTML = tplHTML.replace(re3,dataObj[i].order.id);
// update rid
var re4 = new RegExp("%rid%", "g");
tplHTML = tplHTML.replace(re4,id);
ulObj.append(tplHTML);
// Recent Ordered Item box
var orderObj = $("#order-list-attr-"+id+dataObj[i].order.id);
} // for
}
}
And that gave me the list, provided that there was a cookie called ppmeccookie, with the value of your customerid. This cookie normally gets generated when you have done a paypal checkout before, using this paypal App.
Thanks for the help.

Ajax requests are not made on page load when using KnockoutJS

I am new to the whole front-end client scripting scene and have encountered a few difficulties when working on my most recent project. I have looked around the website and could not find anything that answered my question. There may be something here and I have just not found it because of my inexperience and if there is it would be nice if you can provide a link to those resources.
I am currently working on building a client that makes ajax calls to a cross-domain asp.net web api that I have built. I know that the web api works as it has been tested in fiddler. I have also managed to successfully make calls on a click event.
The problem is that I cannot seem to get this working on page load and with knockoutjs. I have tried to do a simple list that is populated with data when the page loads but when I load the page and check fiddler I can see that the ajax calls are not being made. This possibly explains why when I load the page the content isn't there. I have tried inserting some static data to view model and the binding worked so it seems it may be the case that there is something blocking the ajax calls.
I have looked at examples and have knocked up some code. I cannot see any problems with the code but as I am inexperienced there is certainly a possibility that I am missing something. There may also be more efficient ways to do model binding, if so, I would appreciate any advice from someone more experienced.
The code is:
#{
ViewBag.Title = "KnockoutTesting";
}
<!-- MAIN -->
<div id="main">
<!-- wrapper-main -->
<div class="wrapper">
<ul data-bind="foreach: places">
<li>
<span data-bind="text: title"></span>
</li>
</ul>
</div>
</div>
#section scripts {
<script type="text/javascript" src="../../Scripts/jquery-1.7.2.js"></script>
<script type="text/javascript" src="../../Scripts/knockout-2.1.0.js"></script>
<script type="text/javascript">
function PlacesViewModel() {
var self = this;
function Place(root, id, title, description, url, pub) {
var self = this;
self.id = id;
self.title = ko.observable(title);
self.description = ko.observable(description);
self.url = ko.observable(url);
self.pub = ko.observable(pub);
self.remove = function () {
root.sendDelete(self);
};
self.update = function (title, description, url, pub) {
self.title(title);
self.description(description);
self.url(url);
self.pub(pub);
};
};
self.places = ko.observableArray();
self.add = function (id, title, description, url, pub) {
self.places.push(new Place(self, id, title, description, url, pub));
};
self.remove = function (id) {
self.places.remove(function (place) { return place.id === id; });
};
self.update = function (id, title, description, url, pub) {
var oldItem = ko.utils.arrayFirst(self.places(), function (i) { return i.id === id; });
if (oldItem) {
oldItem.update(title, description, url, pub);
}
};
self.sendDelete = function (place) {
$.ajax({
url: "http://localhost:1357/api/places" + place.id,
type: "DELETE"
});
}
};
$(function () {
var viewModel = new PlacesViewModel();
ko.applyBindings(viewModel);
$JQuery.support.cors = true;
$.get("http://localhost:1357/api/places", function (places) {
$.each(places, function (idx, place) {
viewModel.add(place.PlaceID, place.Title, place.Description, place.URL, place.Public);
});
}, "json");
});
</script>
}
It has been simplified for the sake of getting it to work before I add more functionality.
Thanks for your time.
I believe your problem may lie in your Web API implementation. Both the client and the server must support CORS. According to Carlos' post, Web API does not natively support CORS. His post includes a code sample.

How to view IndexedDB content in firefox

I've been playing with IndexedDB in Firefox (Ubuntu)
Is there any way to visualize IndexedDB databases contents ?
Or do I have to do it programmatic-ally ?
Bleeding edge Chromium builds reportedly allow you to view IndexedDB content in the Resources panel of the Chrome devtools, but only I know of one way to view Firefox IndexedDB content non-programmically and that's to load the .sqlite file directly.
Firefox's IndexedDB .sqlite files are located at /Users/{USER}/Library/Application Support/Firefox/Profiles/{PROFILE}/indexedDB on OS X and should be C:\Users\{USER}\AppData\Roaming\Mozilla\Firefox\Profiles\{PROFILE} on Windows.
I use the excellent (and free) Firefox tool SQLite Manager, which is cross platform.
One thing to keep in mind however is that the contents are often stored as binary blobs and are likely not to be human readable. Keys are stored as text however so they should be able to be read by hand.
Update Although local files remain a great way to view IDB databases and stores, Chrome does now have great tooling available in the Resources panel.
I just downloaded the IndexedDB Browser add-on for Firefox. It works well. Once downloaded it is located in:
Tools > Web Developer > IndexedDB Browser
https://addons.mozilla.org/en-US/firefox/addon/indexeddb-browserupdated-fix/
EDIT:
Since Firefox 26 the files for IndexedDB have moved from {PROFILE}/indexedDB/ to {PROFILE}/storage/persistent/
The current Version (0.1.4) does not handle this change. However it can be easily solved with a symbolic link.
In the new versions of firefox, the developer tools comes with a handy Storage Inspector.
https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector
Currently you have to use the nightly build of firefox to get it
https://nightly.mozilla.org/
Firefox indexedDB location on Ubuntu is:
~/.mozilla/firefox/*.default/storage/persistent/
or
~/.mozilla/firefox-trunk/*.default/storage/persistent/
You can try my indexeddbviewer, it is located on http://linq2indexeddb.codeplex.com.
The following things you'll need to do:
- Add the following references to your page:
<script type="text/javascript" src="../Scripts/jquery-1.7.2.js"> </script>
<script type="text/javascript" src="../Scripts/jquery-ui-1.8.20.js"> </script>
<script type="text/javascript" src="../Scripts/Linq2IndexedDB.js"> </script>
<script type="text/javascript" src="../Scripts/IndexedDBViewer.js"> </script>
This means you need to get jQuery + jQuery UI
And linq2indexedDB (this is my lib and you can get it also on http://linq2indexeddb.codeplex.com).
And to make it work add the following in the body:
<body>
<p><label id="lblDatabaseName" for="txtDatabaseName">Database name:</label> <input type="text" id="txtDatabaseName" /><input type="button" id="btnViewDatabase" value="View database" /></p>
<div id="tabs">
<ul>
</ul>
</div>
</body>
I'll tye to work out an easier way asap.
An other way is just use my linq2indexeddb library, and create an new instance of it like this:
var db = window.linq2indexedDB("Database name", null, true)
if you have done this you can call an attribute viewer, that will give you all the information about the indexeddb database.
db.viewer
let db;
function createDB() {
let dbName = "Jokes";
let dbVersion = 5;
let request = indexedDB.open(dbName, dbVersion);
request.onupgradeneeded = e => {
db = e.target.result
console.log(db);
let jstore = db.createObjectStore("JokeStore", {keyPath: "title"});
let mstore = db.createObjectStore("MockStore", {keyPath: "title"});
alert("upgrade");
}
request.onsuccess = e => {
db = e.target.result
console.log(db);
alert("success");
}
request.onerror = e => {
alert("error"+e.target.error);
}
}
function addRecord(title, text) {
let tx = db.transaction("JokeStore","readwrite");
tx.onerror = e => alert(e.target.error);
let jstoretx = tx.objectStore("JokeStore");
jstoretx.add({title: title, text: text});
}
function viewNotes() {
let tx = db.transaction("JokeStore", "readonly");
let jstore = tx.objectStore("JokeStore");
let request = jstore.openCursor();
request.onsuccess = e => {
let cursor = e.target.result;
if (cursor) {
console.log(cursor.key, cursor.value.text);
cursor.continue();
}
}
}
createDB(); // Creates db if not there or opens an existing one
addRecord("Joke 1", "Knock Knock"); // Adds record
addRecord("Joke 2", "Elephant and the ant"); // Adds record
viewNotes(); // Displays all records in console
I had to read the indexedDB from a WhatsApp Web session, and I did it this way:
function readDB() {
let dbName = "wawc";
let dbVersion = 70;
let request = indexedDB.open(dbName, dbVersion);
request.onsuccess = e => {
let db = e.target.result
let tx = db.transaction("user", "readonly");
let jstore = tx.objectStore("user");
let request = jstore.openCursor();
request.onsuccess = e => {
let cursor = e.target.result;
if (cursor) {
console.log(cursor.key, cursor.value);
cursor.continue();
}
}
}
request.onerror = e => {
console.log("error"+e.target.error);
}
}
readDB();
Console log will show the contents of table 'user' in 'wawc' database.

Resources