I am new to SAP ui5. I have successfully shown data using ODataModel to a table. Now I want to update the data in the table back into the database.
For this I know that we have something called 'update' function of the model in which we can specify the path and the data. My question here is what if I want to give the data in the form of json? How do I retrieve data in the table in the form of json and have it passed to the 'update' method?
Any help would be appreciated. If possible please share example such.
Thanks
You can use the OData model object to get it. Use the path to retrieve the JSON object, update what you need, and then call the update function. Here's an example:
getDataContext : function(oItem) {
var sPath = oItem.getBindingContextPath();
var oModel = this.getView().getModel();
return {
path : sPath,
data : oModel.getObject(sPath)
};
}
From there you can update the data in mDataContext.data as desired, then call the update:
this.getView().getModel().update(
mDataContext.path,
mDataContext.data,
{ // your context, success, error handlers etc }
)
Here's a fully working example that allows you to look at products in Northwind, select one, and increase or decrease that selected product's rating.
Related
i'am working with thingsboard as a plateform to supervise my sensors ,and i want to know if there is any way to add in my dashboard a field that allow me to write comments and those comments will be written in postgresql database ?
i Tried to use input widget but it dosent work
it's a bit harder to make comments that will not overwrite previous comments since you would keep those comments under server attributes (you can't work with postgreSQL directly from ThingsBoard).
Solution to that is that you have input widget and then RPC call to rule chain where you would need to have some script that would put new comment as new field to the JSON array. This obviously requires a bit advanced knowledge about TB.
Also you could probably do that thru "Custom action (with HTML template)".
UPDATE:
The easiest way you can have comments :
Create JSON server attribute on entity (Device, Asset)
(Optional) Create filter that will return only one entity
Create "Update JSON attribute" widget and point it to the server attribute of entity on which you have done first step (help your self with step 2.)
a. have something like this in that window: {"comments":[{"ts":1665472792000,"value":"My comm1"},{"ts":1668163473000,"value":"My comm2"}]}
Create "HTML Value Card" widget, which also points to that entity and it's server attribute
In "HTML Value Card" widget use this code in server attribute post-processing function:
var comm = parsed["comments"]
var returnValue = '';
if (comm){
var commLength = comm.length;
}
for (var i=0;i<commLength;i++){
returnValue += "<span>"+comm[i]["value"]+"<span><br>";
}
return returnValue;
This code in HTML of "HTML Value Card": ${nameOfYourServerAttribute}
Yes, you will have to manually add comments directly to JSON, I don't have time to write some widget for that.
Take a look at my example:
I have a sap.m.Table whose "items" are bound to oData v2 model. I need to delete item on click on delete icon. Here is what I do:
On click of delete icon, I get all the rows in the model, delete the one in question and set the property of model again.
However since the model is changed, it triggers a backend round trip and brings the latest data and table shows the original rows again.
I tried setting binding mode to OneTime but that does not work. Also tried setting RefreshAfterChange to false but even then service was called again.
Here is my code -
Controller
onInit: function() {
var oModel = new sap.ui.model.odata.v2.ODataModel("url", {
json: true,
useBatch : false,
refreshAfterChange: false,
defaultBindingMode: "OneTime"
});
this.getView.().setModel(oModel, "model1");
},
onDeleteIconPress : function(oEvent) {
// get the selected row
// get all the rows in oOriginalRows
// loop over oOriginalRows and delete the selected row from it
// set the model to reformed oOriginalRows
this.getView().getModel("omodel1").setProperty("/", oOriginalRows);
// Till this point every thing looks fine. I can see changes in the model
// refresh is called automatically and data service triggers backend call
// This fetches original data again and table shows all data again
}
How can I not trigger the round trip again? I need to update the locally
Your approach won't work with a ODataModel as it is strictly server side. Please use the corresponding remove method to delete an entity from the server.
Since Odata is server side model, it always triggered a round trip. So I did not bind my sap.m.Table to Data model. Instead I triggered a read manually. On success I copied the data received to local JSON model. I bound my table items to this JSON model. Now the delete button works just fine.
// Define a JSON Model
oJsonModel = new sap.ui.model.json.JSONModel();
//oModel is Odata model defined in manifest file
oModel.read("/entity1", {
success: function(oData, oResponse){
oJsonModel.setProperty("/entity1", oData.results);
// bind oJsonModel to table here
}
}
I have a view that inherit the following:-
#model MvcApplication.Models.Application
But i need to know if it is possible to pass JSON objects to my view in the same way i am passing the model objects?
Since i have the following Controller:-
public ActionResult ListPackages()
{
using (var client = new WebClient())
{
var query = HttpUtility.ParseQueryString(string.Empty);
//code goes here ....
return Content(json, "application/json");
}
}
which returns JSON using a API call, and then i am displaying the JSON on the view using JavaScript as follow:
$.ajax({
url: $('#geturl').data('url'),
type: 'GET',
cache: false,
success: function (result) {
$.each(result.data, function (key, val) {
var str = val.packageName;
$('<li/>', { text: str })
.appendTo($('#products'));
});
}
The problem with displaying the JSON using JavaScript is that it will make too difficult for me to work easily with the JSON objects, such as creating links based on the returned JSON or creating table that contain the JSON. So my question is: Is it possible to pass a JSON object instead of a Model object from my controller to my view?
Server- vs client-side confusion
You're talking two things here:
Creating a view: controller passes model to the view on the server side and it doesn't make much sense to do so using JSON, because an in-memory object is being passed to view engine.
Consuming JSON data on the client: what you're talking about here is client-server Ajax communication where you request data from the client and get JSON returned from the server. This has arguably nothing to do with model data being passed to the view
Best solution using JSON
In order to easily consume JSON data (in your case it's an array of packages) on the client to generate resulting populated HTML is to use some sort of templating on the client side. jQuery used to have non-final templating plugin which is now a separate project. I've had great experience with it but there are other plugins as well. Use the one that you feel most comfortable with its syntax.
Where to put those templates?
If you know the structure of your JSON objects passed from the server at the point of creating your view, you can put templates in the view itself and they'll just wait untill being used on the client.
If you don't know the structure of your JSON objects then you'll have to pass templates either along JSON object or as a separate request.
The first approach is the usual one, the second one is rarely used and is much more dynamic.
Best solution not using JSON
If you don't like parsing JSON to HTML results (either manually or using templates), you can always make Ajax requests to your controller action, which would return a prepared HTML as a partial view instead of JSON result. This way, you could easily just put that HTML onto your page without any JSON data manipulation.
What do you gain here? Well suppose you have this functionality in your app:
You have a view that displays a paged list of packages.
When user first accesses the page first page of packages are being returned
Paging to next page is done via Ajax and the list is being replaced by returned data
If you'd create a partial view for your subsequent Ajax request, you can use the same partial view in your main view to display the first page of packages. This will ensure that you only have to change one partial view and display would change on inital page load as well as subsequent package paging.
If you used view + JSON + templating that means that you have to maintain two presentations of package list: the one being used in the view for the first page and the template that displays subsequent paging.
Which one then?
All things being equal it makes the second solution better. But the choice of course depends on your case (of things not being equal) and you should be able to determine which one is best in your scenario.
No, you can't. A view must be strongly typed to a model. So one solution would be to deserialize this JSON into a model object before passing it to the view:
public ActionResult ListPackages()
{
using (var client = new WebClient())
{
var query = HttpUtility.ParseQueryString(string.Empty);
//code goes here ....
var model = new JavaScriptSerializer().Deserialize<MyViewModel>(json);
return View(model);
}
}
where MyViewModel would of course reflect the JSON structure that you are working with.
I'm new to Backbone.js and working with JSON.
I'm having trouble working with the following JSON:
http://pastebin.com/FFEwc0Fb
What I want to achieve is to
create a model of that JSON data
bind the model to a view
bind the view to a template and learn how to show certain attributes of the data e.g. feed->title and the titles of each playlists which is feed->entry->array->title
Could someone provide sample code of that does the above or point me in the right direction?
Possible Alternative Solutions: I'm also using Rails in my App so I could use try using Rails to turn the JSON into the JSON I want it to be ...
look at the parse method on models and collections. After you make your fetch the response is always passed through a parse function that you define on your model or collection. In there you can go through the object and build up the attributes to be set to the model how you want them. For example:
parse: function(response) {
var attrs = {
title: response.feed.title,
author: response.feed.author
};
return attrs;
}
That's a small example of how you could do it within backbone.
I have a bunch of text inputs on my page (HTML.TEXTBOX, generated through for loop), and I want to read their values and commit to database only when user has modified something in those textboxes.
What would be a proper way to do that? (Do you think it may make more sense to commit the entire thing to database if number of textboxes is less than 100?)
Also, in general, how would I read values from a bunch on textboxes and commit to the database? I would need something that uses a key-value pair, where key would be the id and value would be that input in the textbox.
Unless you use for example JavaScript and hidden fields to keep track of user changes, there is no way for you to know which fields have been modified without querying the database, since the web in general, and ASP.NET MVC in particular, is stateless. However, if you loop out the fields with their values filled in with data stored in an object, you can probably save that object in a session variable to compare against on the next request.
Pseudo-example:
public ActionResult GetFormView()
{
var values = (select relevant information from db and store in a
IQueryable<Dictionary<string, string>> or something similar
where you have a relation between input field id/name and value);
Session["TheInputListValues"] = values;
return View(values); // Your view renders your list of input fields
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveChanges(FormCollection form)
{
var oldValues = (Dictionary<string, string>)Session["TheInputListValues"];
var changedValues = new Dictionary<string, string>();
foreach(string key in form.AllKeys)
{
if(oldValues.ContainsKey(key))
{
if (oldValues[key] != form[key])
{
changedValues(key, form[key]);
}
}
}
SaveToDB(changedValues);
return Redirect("SomeWhereElse"); // PRG is king!
}
I haven't tested this implementation, but it's worth a try =)
I have done something similar using jQuery and it works pretty well. Attach a behavior to the textboxes where if the data changes then submit it's value to an action that saves the data.
$(function(){
$("input[type='text']").change(function(){
$.post("/SaveChanges",{id: $(this).attr("id"),value : $(this).attr("text")});
});
});
This would be assuming you had ID's that were some sort of unique key to you record on each input.
<input id="4576" name="4576"/>
you could also have a callback that would say add a class to this field letting them know that the information was saved by changing it to green or something.
Check this out for more details:
http://docs.jquery.com/Ajax/jQuery.post