I need to set the property to DataSet during onInit, to change the visiblity of some controls in my View. I could solve this problem with setting the visibility dynamically in controller. But I want to use the expression binding and the visible property in the View to set visibilites.
I'm getting an error in the function OnStartSetVisibilites. self.getView().getBindingContext() returns UNDEFINED. Without the sPath, I can't use setProperty. And without setProperty, my View-Controls don't know the visible-value.
How to fix this?
View:
<uxap:ObjectPageSubSection visible="{= ${Responsible} === '1'}" id="leader">
</uxap:ObjectPageSubSection>
OnInit in View-Controller:
onInit: function () {
var startupParameters = this.getOwnerComponent().getComponentData().startupParameters;
var sWorkitem = startupParameters.TASK[0];
this.setModel(this.getOwnerComponent().getModel());
this.getModel().metadataLoaded().then(function () {
var sObjectPath = this.getModel().createKey("DataSet", {
Workitem: sWorkitem
});
this.getView().bindElement({
path: "/" + sObjectPath
});
}.bind(this));
var self = this;
var model = this.getOwnerComponent().getModel();
this.getModel().read("/CharSet", {
success: function (response) {
$.sap.Chars = response.results;
self.onStartSetVisibilities(model, self);
}
});
// self.getView().attachAfterRendering(function () {
// self.onStartSetVisibilities(model, self);
// });
}
OnStartSetVisibilities:
onStartSetVisibilities: function (model, self) {
var char = model.getProperty(ā€˛GeneralData/Char");
if (char !== "" || char !== null) {
model.setProperty(self.getView().getBindingContext().sPath + "/Responsible",
this.getResponsibleForChar(char));
}
}
I put together some code which might solve your issue (it's untested so it may contain syntax errors!).
I introduced the concept of Promises which simplifies the asynchronous behavior of JS. I also replaced some of the inner functions with Arrow functions so you don't have to deal with that or self. Arrow functions basically use the this of the scope they are defined within.
Your app should now have a proper flow.
First you bind the view.
After the view is bound you read the CharSet.
After the data is read you set the visibility stuff
onInit: function () {
const startupParameters = this.getOwnerComponent().getComponentData().startupParameters;
const sWorkitem = startupParameters.TASK[0];
this._bindView(sWorkitem)
.then(() => this._readCharSet())
.then(() => this._setVisibilities())
},
_bindView: function (sWorkitem) {
return new Promise((resolve) => {
const oModel = this.getOwnerComponent().getModel();
oModel.metadataLoaded().then(() => {
const sPath = "/" + oModel.createKey("DataSet", {
Workitem: sWorkitem
});
this.getView().bindElement({
path: sPath,
events: {
change: resolve,
dataReceived: resolve
}
});
});
});
},
_readCharSet: function () {
return new Promise((resolve) => {
const oModel = this.getOwnerComponent().getModel();
oModel.read("/CharSet", {
success: resolve
});
});
},
_setVisibilities: function () {
const oModel = this.getOwnerComponent().getModel();
const sChar = oModel.getProperty("GeneralData/Char");
if (sChar) {
// ...
}
}
Related
I have a electron that looks like this
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electron', {
electronStore: {
get(val) {
ipcRenderer.send('electron-store-get', val);
},
set(property, val) {
ipcRenderer.send('electron-store-set', property, val);
},
// Other method you want to add like has(), reset(), etc.
},
});
and ipcMain that looks like this
ipcMain.on('electron-store-get', async (event, val) => {
store.get(val);
// console.log(reply);
// return reply;
// event.reply('electron-store-get', reply);
});
ipcMain.on('electron-store-set', async (event, property, val) => {
// console.log(val);
store.set(property, val);
});
When I was trying to call the function via electron.electronStore.get(), it returns undefined
let a = window.electron.electronStore.get('test');
console.log(a);
However, I've tested that on the line of ipcRenderer.send(""), I was able to receive data by setting as below
let result = ipcRenderer.send('electron-store-get',val);
console.log(result);
Which mean, ipcRenderer is not undefined and set has been successfuly, get as-well, just it went missing when i invoke the ipcMain Get functions
Your current preload API isn't actually returning anything:
get(val) {
ipcRenderer.send('electron-store-get', val);
}
You'll want to either use the synchronous API: return ipcRenderer.sendSync('electron-store-get', val) and then have your handler in main do:
ipcMain.on('electron-store-get', (event, val) => {
event.returnValue = store.get(val);
});
Or make the preload API async:
get(val) {
return ipcRenderer.invoke('electron-store-get', val);
}
ipcMain.handle('electron-store-get', (event, val) => {
return store.get(val);
});
And then:
let a = await window.electron.electronStore.get('test');
I am rendering extension on the Work item page using
<WebpageControlOptions AllowScript="true" ReloadOnParamChange="true">
<Link UrlRoot="http://.../extension/Validate-extension/1.0.69/assetbyname/workItemNotifications.html"/>
</WebpageControlOptions>
Following is the html/js code:
var workItemID = 0;
VSS.init({
explicitNotifyLoaded: true,
usePlatformScripts: true
});
VSS.ready(function () {
var currentContext = VSS.getWebContext();
VSS.register(VSS.getContribution().id, function (context) {
return {
// event handlers, called when the active work item is loaded/unloaded/modified/saved
onFieldChanged: function (args) {
if (!changedFields[args.id]) {
changedFields[args.id] = [];
changedFieldCount[args.id] = 0;
}
$.each(args.changedFields, function (key, value) {
if (!changedFields[args.id][key]) {
changedFields[args.id][key] = value;
changedFieldCount[args.id]++;
}
});
},
onLoaded: function (args) {
console.log("OnloadNotification");
VSS.require(["TFS/WorkItemTracking/Services"], function (workItemServices) {
workItemServices.WorkItemFormService.getService().then(function (workItemFormSvc) {
if (workItemFormSvc.hasActiveWorkItem()) {
console.log("Active work item is available.");
workItemFormSvc.getFieldValues(["System.Id"]).then(
function (value) {
var val = JSON.stringify(value);
$.each(value, function (key, values) {
if(key == "System.Id"){
workItemID = values;
}
});
});
}
else {
console.log("Active work item is NOT available.");
}
});
});
},
onUnloaded: function (args) {
},
onSaved: function (args) {
changedFieldCount[args.id] = 0;
changedFields[args.id] = [];
},
onReset: function (args) {
changedFieldCount[args.id] = 0;
changedFields[args.id] = [];
},
onRefreshed: function (args) {
changedFieldCount[args.id] = 0;
changedFields[args.id] = [];
}
};
});
VSS.notifyLoadSucceeded();
});
$(document).ready(function () {
$("#btnValidate").click(function () {
var getResponse = ValidateUser();
VSS.require(["TFS/WorkItemTracking/Services"], function (_WorkItemServices) {
var wiServiceNew = _WorkItemServices.WorkItemFormService.getService();
wiServiceNew.setFieldValue("System.Title", "Title set from your group extension!");
});
});
});
2 things which I am trying to achieve
After button click event to validate user, I have to access the Work Item fields after successful validation. Unable to access _WorkItemServices.
Not able to to get the Work Item fields.
When I set workItemID variable OnLoad event, it resets to 0 when a tab is clicked, value is not getting retained which is set OnLoad.
You may try to interact with the IWorkItemFormService service. For example:
import {
IWorkItemChangedArgs,
IWorkItemFieldChangedArgs,
IWorkItemFormService,
IWorkItemLoadedArgs,
WorkItemTrackingServiceIds
} from "azure-devops-extension-api/WorkItemTracking";
Check the sample here:
https://github.com/microsoft/azure-devops-extension-sample/blob/master/src/Samples/WorkItemFormGroup/WorkItemFormGroup.tsx
I have a problem creating a hook calling a stored procedure.
My custom service hooks (customservice.hooks.js) are :
const callstored = require('../../hooks/callstored')
module.exports = {
before: {
all: [],
find: [callstored()],
get: [],
create: [],
update: [],
patch: [],
remove: []
},
...
My service class (customservice.class.js):
const mysql = require('mysql')
class Service {
constructor (options) {
this.options = options || {};
}
find (params) {
return Promise.resolve( [] );
}
get (id, params) {
return Promise.resolve({
id, text: `A new message with ID: ${id}!`
});
}
create (data, params) {
if (Array.isArray(data)) {
return Promise.all(data.map(current => this.create(current)));
}
return Promise.resolve(data);
}
update (id, data, params) {
return Promise.resolve(data);
}
patch (id, data, params) {
return Promise.resolve(data);
}
remove (id, params) {
return Promise.resolve({ id });
}
}
module.exports = function (options) {
return new Service(options);
};
module.exports.Service = Service;
And my service (customservice.service.js) :
const createService = require('./rankingvotes.class.js');
const hooks = require('./rankingvotes.hooks');
module.exports = function (app) {
const paginate = app.get('paginate');
const options = {
name: 'rankingvotes',
paginate
};
// Initialize our service with any options it requires
app.use('/rankingvotes', createService(options));
// Get our initialized service so that we can register hooks and filters
const service = app.service('rankingvotes');
service.hooks(hooks);
app.publish(() => {
});
};
And finally my hook is (callstored.js)
const Sequelize = require('sequelize');
module.exports = function () {
return function (hook) {
sequelize = hook.app.get('sequelizeClient');
let result=[];
return sequelize.query('CALL RANKING();',{
nest: true,
raw: true }).then(function(response){
console.log(response[0]) //data are correct
hook.data=response[0];
return hook;
}).error(function(err){
console.log(err);
return hook;
});
}
}
If I check the console I got data correctly, but nothing calling from a REST client like Postman.
Any idea? Thank you.
If you want to change the response you have to set hook.result.
const Sequelize = require('sequelize');
module.exports = function () {
return async hook => {
try {
const sequelize = hook.app.get('sequelizeClient');
const response = await sequelize.query('CALL RANKING();',{
nest: true,
raw: true
});
console.log(response[0]) //data are correct
context.result = response[0];
} catch(error) {
console.error(error);
}
return hook;
}
}
hook.data is the request data and is only available for create, update and patch.
Keep in mind that setting hook.result will skip your custom service find if it is set in a before hook.
I have a viewmodel defined following:
var ViewModel = function() {
var self = this;
self.property1 = ko.observable().extend({ required: true });
self.property2 = ko.computed(function() {
return self.property1();
});
self.form_onsubmit = function (form) {
if (!self.isValid()) {
console.log("error");
}
return false;
};
};
$(function () {
ko.applyBindingsWithValidation(new ViewModel());
});
when i call the form_onsubmit function, an error occured:
TypeError: self.isValid is not a function
if (!self.isValid()) {
how to solve it, thanks^^^
add
self.errors = ko.validation.group(self);
to your viewmodel
when I bind custom plugin in a such way it works ok:
<script type="text/javascript">
$("#MyGrid").customFilter({ postUrl: '#(Url.Action("SearchOffers", "Department"))' });
</script>
but if i want to wait till document is ready:
<script type="text/javascript">
$(document).ready(function() {
$("#MyGrid").customFilter({ postUrl: '#(Url.Action("SearchOffers", "Department"))' });
});
</script>
$("#MyGrid").customFilter is not a function error appears. Why?
Custom plugin:
(function ($) {
var theGrid;
var filterTimeout;
var mouseIsInside = false;
var postUrl;
var methods = {
init: function (options) {
return this.each(function () {
postUrl = options.postUrl;
theGrid = $(this);
...
});
},
method2: function () {
// ...
}
};
$.fn.customFilter = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.customFilter ');
}
};
//private functions
function isFilterable(th) {
var name = th.children("a").text();
return (name.length > 0) ? true : false;
}
...
})(jQuery);
The script file should be registered in Telerik().ScriptRegistrar()
#Html.Telerik().ScriptRegistrar().DefaultGroup(group => group.Add("~/Scripts/gridFilter.js"))