Make single column editable in a UI5 smart table - javascript

I want to create a smart table with an editable column. I am using the metadata annotations to generate the table. The table property (editable = "true") makes all the columns editable. In my case, I want to make only a single column editable. I tried with the property sap:updatable="true" but it didn't work. Any ideas.
Thanks in advance.
This is my view by the way:
<mvc:View
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
controllerName="QuickStartApplication3.controller.View1"
xmlns:smartFilterBar="sap.ui.comp.smartfilterbar"
xmlns:smartTable="sap.ui.comp.smarttable">
<smartFilterBar:SmartFilterBar
id="smartFilterBar"
entityType="Product">
<smartFilterBar:controlConfiguration>
<smartFilterBar:ControlConfiguration
key="ProductId"
visibleInAdvancedArea="true"
preventInitialDataFetchInValueHelpDialog="true" >
</smartFilterBar:ControlConfiguration>
</smartFilterBar:controlConfiguration>
<smartFilterBar:controlConfiguration>
<smartFilterBar:ControlConfiguration
key="Name"
visibleInAdvancedArea="true"
preventInitialDataFetchInValueHelpDialog="true" >
</smartFilterBar:ControlConfiguration>
</smartFilterBar:controlConfiguration>
<smartFilterBar:controlConfiguration>
<smartFilterBar:ControlConfiguration
key="Category"
visibleInAdvancedArea="true"
preventInitialDataFetchInValueHelpDialog="true" >
</smartFilterBar:ControlConfiguration>
</smartFilterBar:controlConfiguration>
</smartFilterBar:SmartFilterBar>
<smartTable:SmartTable
id="smartTable_ResponsiveTable"
smartFilterId="smartFilterBar"
tableType="ResponsiveTable"
editable="false"
entitySet="Products"
useVariantManagement="false"
useTablePersonalisation="true"
header="Products"
showRowCount="true"
useExportToExcel="true"
enableAutoBinding="true">
</smartTable:SmartTable>
</mvc:View>

I don't have enough rep to put a simple comment to your question but could you provide a sample of your view so that I can understand more precisely what you do?
Have you tried the use the sap.m.Table object as detailed here in the documentation :
https://sapui5.hana.ondemand.com/explored.html#/sample/sap.m.sample.TableEditable/preview
In order to have only certain cell editable you can manage it throught the template used see below how I changed the template in the onInit method of the controller:
onInit : function(evt) {
this.oModel = new JSONModel(jQuery.sap.getModulePath(
"sap.ui.demo.mock", "/products.json"));
this.oTable = this.getView().byId("idProductsTable");
this.getView().setModel(this.oModel);
this.oReadOnlyTemplate = this.getView().byId(
"idProductsTable").removeItem(0);
this.rebindTable(this.oReadOnlyTemplate, "Navigation");
this.oEditableTemplate = new sap.m.ColumnListItem({
cells : [ new sap.m.ObjectIdentifier({
title : "{Name}",
text : "{ProductId}"
}), new sap.m.Input({
value : "{Quantity}",
description : "{UoM}"
}), new sap.m.Input({
value : "{WeightMeasure}",
description : "{WeightUnit}"
}), new sap.m.Input({
value : "{Price}",
description : "{CurrencyCode}"
}) ]
});
If you don't use this object, then please tell me which one, I might be able to help.

Please have a look at the “Preview”-screenshot and the metadata.xml.
What happens if you set editable = "true" and annotate all properties of ‘Products’ with sap:updatable=”false”,
except for the single property that shall be editable, which you set to sap:updatable=”true”.
Don’t annotate entity set ‘Products’ with sap:updatable (or make sure that sap:updatable=”true”).

Related

changing model property value is changing the same property in other object

im new to vue , i want user to be able to add some specific social media links to the page and edit some properties like it's text
i have 2 objects in my data , models and defaults
defaults contains selectable option for social media links and their initial values
basically i copy the default value into models and let the user customize the model via inputs
data () {
return {
models : [] ,
defaults : {
twitter : { id : null , placeholder : 'my twitter' , icon : 'twitter' , text : null , 'link' : null } ,
instagram : { id : null , placeholder : 'my instagram' , icon : 'instagram' , text : null , 'link' : null } ,
tiktok : { id : null , placeholder : 'my tiktok' , icon : 'tiktok' , text : null , 'link' : null } ,
} ,
}
} ,
so there a select menu for user to select which social he wants to add to the page
Select :
<ul >
<li v-for="(social, index ) in defaults" :key="index">
<a #click="appendSocial(index)">
{{ index }}
</a>
</li>
</ul>
here is my #click="appendSocial(index)" function
appendSocial(type){
let typedefault = this.defaults[type];
this.models.push(typedefault)
},
and finally i show my models to user and provide an input for editing it's text via v-model
<div v-for="(model, index) in models" v-bind:key="model.id">
<a class="button-preview">
{{ model.text === null ? model.placeholder : model.text }}
</a>
<label>Text</label>
<input type="text" v-model="model.text" :key="index" :placeholder="model.placeholder">
</div>
so here is the problem , for some reason changing the models properties will change the same property in defaults ... and changing defaults properties will change the same property models !!
like if i add a twitter menu to the page and change it's text (model.text) to abc via v-model ... it will also change defaults.twitter.text to abc
to better demonstrate the problem i've added some console log to my appendSocialfunction
appendSocial(type){
let typedefault = this.defaults[type];
console.log(`-------- default object for ${type} -----------`);
console.log(typedefault);
this.addElement(typedefault);
},
here is the result
1 - i've selected a twitter link and added to my models , you can see defaults.twitter.text is null
2 - i've change my model.text (i suppose it would be models[0].text) to abc
3 - i've added another twitter link to my page ... this time defaults.twitter.text is also abc
also changing defaults properties will effect all the models the has been getting their value from that default object
like if i change the defaults.instagram.text to xyz all my models which have got their initial values from defaults.instagram will also change their text to xyz
it's like they are referencing each other , but i haven't passed the value between 2 objects by reference
im not sure what's happening here and how can i prevent this ?
This is because
let typedefault = this.defaults[type];
this.models.push(typedefault)
Is storing the reference to the object into your this.models array. And so if you mutate the element, you're by default changing the base object. A quick and dirty way of doing a deep clone is the following.
let typedefault = this.defaults[type];
let clonedObj = JSON.parse(JSON.stringify(typedefault));
this.models.push(clonedObj)
Note: Lodash library does have a proper deep clone functionality.
https://www.geeksforgeeks.org/lodash-_-clonedeep-method/

Unable to read value from document

I'm a novice in MVC, Below is my code
I am unable to read the value of an ID and use that in an decision statement, I am getting "The name "Text" does not exist in current context", I need to work on the if statement based on the value I get from my document.getElementById
#{
var grid = new WebGrid(Model.Abc, canPage: true, canSort: true, rowsPerPage: 50);
}
#{
var gridColumnsNew = new List<WebGridColumn>();
gridColumnsNew.Add(grid.Column("Details", header: "Id"));
<text>
var obj = document.getElementById("NextAction").value;
</text>
if (#text.obj == "Start")
{
gridColumnsNew.Add(grid.Column("Temp"));
}
}
Try using
document.getElementsByName("NextAction").value;
I have seen in my case that Blazor changes Id to name.
Note: I am using DevexpressBlazor
Did you checked if you are able to see on the html generated that ID?
If yes, Did you have any JS error before?
Looks like the ID not was generated or the place where you are run the getElementById don't have visibility to your specific code.
You are mixing razor syntax and javascript. The line var obj = document.getElementById("NextAction").value; is javascript and should go inside <script> tag. You can't call javascript functions from razor code.
Solution:
Assuming you have a controller named GridController.cs and a view named Grid.cshtml. Inside your controller add a new HttpPost action:
[HttpPost]
public IActionResult NextAction(string nextAction)
{
ViewData["NextAction"] = nextAction;
return View("Grid");
}
Inside the view add a form that posts the nextAction value to the controller:
<form asp-action="NextAction" asp-controller="Grid">
<input type="hidden" value="Start" name="nextAction" />
<button type="submit">Start</button>
</form>
The controller added the NextAction value in the ViewData dictionary so now the view can access it:
#{
var gridColumnsNew = new List<WebGridColumn>();
gridColumnsNew.Add(grid.Column("Details", header: "Id"));
if (ViewData["NextAction"] == "Start")
{
gridColumnsNew.Add(grid.Column("Temp"));
}
}
You are getting that error because you are using #text.obj. In Razor, once you attached # before any identifier, it considers it a C# or VB variable.
Since we don't have your entire page, you may need to clarify where the source of the NextAction. It will be helpful. See a sample of something similar.
#if(item.Ward == "start")
{
gridColumnsNew.Add(grid.Column("Temp"));
}
The item is from the model I am iterating to form the grid.

SAPUI5 List Bind Aggregation get Value of the list

I have list and I am using bindaggregation to bind my model data.
below is my code.
Controller
this.oList = this.byId("list");
this.oListItem = this.byId("MAIN_LIST_ITEM").clone();
this.oList.bindAggregation("items", {path: '/myListSet',
template: this.oListItem,
filters: this.searchFilters,
});
this.registerMasterListBind(this.oList);
console.log("firststatus"+this.oListItem.getFirstStatus().getText());
}
My requirement is to manipulate the value of the firststatus, Fristly I am trying to get the value with the below line and unfortunately it is diplaying null value. Can someone advise how to get the value of the firststatus?
this.oListItem.getFirstStatus().getText()
Update - View
<List id="list" growing="true" growingThreshold="20" growingScrollToLoad="true" showNoData="true" mode="{device>/listMode}"
select="_handleSelect">
<ObjectListItem id="MAIN_LIST_ITEM" type="{device>/listItemType}" press="_handleItemPress" title="{sName}">
<markers>
<ObjectMarker type="Flagged"/>
</markers>
<firstStatus>
<ObjectStatus text="{Status1Txt}"/>
</firstStatus>
<attributes>
<ObjectAttribute id="ATTR1" text="{SNumber}"/>
<ObjectAttribute id="ATTR2" text="{PTxt}"/>
</attributes>
<secondStatus>
<ObjectStatus text="{Status2Txt}"/>
</secondStatus>
</ObjectListItem>
</List>
So if I understand correctly, you're trying to retrieve the status text of an entry, but what you're actually doing is retrieving the default template of the ObjectListItem.
If you want the correct value for an entry, you can try this. This returns a filled clone of the default template. You can't clone() an empty template and expect it to have values in it.
Hope this helps, lampstand.
this.byId("list").getItems()[0].getFirstStatus().getText();

CQ5 nested multi-field with select option

I will need to add the values that editor writes them in textfield from dialog panel into a <select> option. I have created the multi-field option for the dialog component, but not sure how I should get values in the <select> it self.
I'm using the JS widget for multi-field, you can find it here. I know that the multi-field JS should return a JSON array of options, how do I achieve this in my case?
Here's my XML markup:
<developer
jcr:primaryType="cq:Widget"
title="Data"
xtype="panel">
<items jcr:primaryType="cq:WidgetCollection">
<developer
jcr:primaryType="cq:Widget"
fieldDescription="Click the '+' to add a new data"
fieldLabel="Dev Data"
name="./devdata"
xtype="multifield">
<fieldConfig
jcr:primaryType="cq:Widget"
xtype="devprofile"/>
</developer>
</items>
</developer>
JavaScript that is adding the textfield for multi-field
this.developerName = new CQ.Ext.form.TextField({
fieldLabel : "Developer's Name",
allowBlank: true,
width : 400,
listeners : {
change : {
scope : this,
fn : this.updateHidden
},
dialogclose : {
scope : this,
fn : this.updateHidden
}
}
});
this.add(this.developerName);
And the markup:
<c:if test="${not(empty(developerName))}">
<select id="use-names" class="js-example-basic-multiple">
<option>Example</option>
<option>${developerName}</option>
</select>
</c:if>
Please let me know if you need more detailed shared.
ACS commons has pretty good working example of custom multifield. Take a look at https://adobe-consulting-services.github.io/acs-aem-commons/features/widgets.html
Just replace textarea with your dropdown and you will have what you need..

SAPUI5 Check model attribute in view

I have a model attached to my view:
Controller code:
var model =
{
title:"Scan RFID container",
question:"Please scan the RFID tag on the container",
answer:"",
type:"input",
options:"",
transaction : ""
};
var oQuestion = new sap.ui.model.json.JSONModel();
oQuestion.setData(model);
this.getView().setModel(oQuestion, "containerChecks");
In my view I can set the texts etc by using the curly brackets. This ofcourse only works for sapui5 elements that parse this content.
View code
this.page = new sap.m.Page({
title: "{containerChecks>/title}",
content: [
new sap.m.Text({
text: "{containerChecks>/question}"
})
],
});
However I want to do a check based on my model attribute 'options'.
I tried:
var options = this.getModel("containerChecks").getProperty("options");
but getModel returns null
As your setting the model in View by using this.getView().setModel() how can you access the model through this.getModel() try this
var options = this.getView().getModel("containerChecks").getProperty("options");
If your using above statement in a Controller.
I am sure that it may give you the options value.

Categories