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"))
Related
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) {
// ...
}
}
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
Im getting a TypeError: undefined is not a function. when using Angular..
Im loading the scripts in this ordering:
_Layout.cshtml
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-resource.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/Scripts/toastr.js"></script>
<script src="~/Scripts/App/app.js"></script>
<script src="~/Scripts/Authentication/authenticationRepository.js"></script>
<script src="~/Scripts/Authentication/authenticationController.js"></script>
<script src="~/Scripts/Notification/notificationFactory.js"></script>
#RenderSection("scripts", required: false)
app.js
var app = angular.module("seducApp", ['ngRoute', 'ngResource'])
.config(function ($routeProvider, $locationProvider) {
//Login
$routeProvider.when('/User/Login', {
templateUrl: '/templates/User/Login.html'
}).
otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
});
authenticationController.js
app.controller("authenticationController", function ($scope, authenticationRepository, notificationFactory, $location) {
$scope.login = function (loginVM, returnUrl) {
notificationFactory.error = false;
authenticationRepository.login(loginVM, returnUrl).$promise.then(
function () { $location.url('Home'); },
function () { notificationFactory.error('Fejl i login', 'Fejl'); });
};
$scope.master = {};
$scope.reset = function () {
$scope.loginVM = angular.copy($scope.master);
};
$scope.isUnchanged = function (loginVM) {
return angular.equals(loginVM, $scope.master);
};
$scope.reset();
});
authenticationRepository.js
'use strict';
app.factory('authenticationRepository', function ($resource) {
return {
login: function (loignVM, returnUrl) {
return $resource('/api/User').Login(loignVM, returnUrl);
}
};
});
Im new to Angularjs and I can find the problem..
You are calling $resource('/api/User').Login(...), but the Login() method is not defined.
If you want your resource class to have special/custom actions (i.e. methods), you need to specify that on creation (along with the necessary properties (e.g. method, params etc)).
(More info here).
app.factory('authenticationRepository', function ($resource) {
var User = $resource('/api/User', {
Login: {
method: ...,
[headers: ...,]
[params: ...,]
[data: ...,]
...
}
});
return {
login: function (loignVM, returnUrl) {
return User.Login(loignVM, returnUrl);
}
};
});
I works like this:
'use strict';
app.factory('authenticationRepository', function ($resource) {
return {
login: function (model) {
return $resource('/api/User/Login').save(model);
}
};
});
'use strict';
app.controller("authenticationController", function ($scope, authenticationRepository, $location, notificationFactory) {
$scope.login = function (model) {
notificationFactory.error = false;
authenticationRepository.login(model).$promise.then(
function () { $location.url('/Home/Index');},
function (response) { notificationFactory.error = response.data; });
};
$scope.master = {};
$scope.reset = function () {
$scope.model = angular.copy($scope.master);
};
$scope.isUnchanged = function (model) {
return angular.equals(model, $scope.master);
};
$scope.reset();
});
I'm using angularjs to bring some data from server,
it's works perfectly.
Here is the code:
myAppcontroller("AgentCtrl", function ($scope, leadsService) {
$scope.showUsers = false;
$scope.cityName = { 'query': ''};
$scope.findAgent = function() {
leadsService.get("/api/usersapi/agents/" + $scope.cityName.query).then(function(out) {
$scope.agents = out;
$scope.showUsers = true;
$scope.selectedOption = $scope.agents[0];
});
};
$scope.init = function (cityName) {
$scope.cityName.query = cityName;
if ((typeof cityName !== "undefined")) {
$scope.findAgent();
}
};
$scope.$watch('cityName.query', function (newValue, oldValue) {
$scope.cityName.query.watch = newValue;
});
});
Now I have a validation error in Chrome... (I'm using jQuery validation).
Here is the code I'm using to disable this error:
$.validator.addMethod('date', function (value, element, params) {
if (this.optional(element)) {
return true;
}
var isValid = /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2} \d{2}:\d{1,2}:\d{1,2}$/.test(value);
alert(isValid);
return isValid;
}, '');
But when I use the jquery code angularjs stops working...
Some one have met this issue??? If so how to solve it?
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