how do I decorate a custom method inside my CrudController so that the Swagger documentation would be shown as the one from getManyBase? Meaning I need to have all of the filter fields.
I tried this way
#Get('/projects')
#UseInterceptors(CrudRequestInterceptor)
#ApiResponse({ status: 200, type: Project, isArray: true })
getManyProjects(#ParsedRequest() req: CrudRequest, #Request() request)
: Promise<GetManyDefaultResponse<Project> | Project[]> {
const { id, role } = request.user;
if (role === UserRoles.User) {
req.parsed.filter.push({
field: 'userId',
operator: 'eq',
value: id,
});
}
return this.projectService.getMany(req);
}
but the Swagger docs shows empty for the query parameters,
while I'm expecting something like getManyBase.
Funny thing is, the method would work properly if I send the filter string, but I need Swagger to display them as well.
Advice?
See this area in the nestjsx/crud repo.
If you add something like this to your constructor that should do it:
import { Swagger } from '#nestjsx/crud/lib/crud';
...
constructor() {
const metadata = Swagger.getParams(this.getManyProjects);
const queryParamsMeta = Swagger.createQueryParamsMeta('getManyBase');
Swagger.setParams([...metadata, ...queryParamsMeta], this.getManyProjects);
}
In my version "#nestjsx/crud": "^5.0.0-alpha.3"
import { Swagger } from '#nestjsx/crud/lib/crud';
...
constructor() {
const metadata = Swagger.getParams(this.getManyProjects);
const queryParamsMeta = Swagger.createQueryParamsMeta('getManyBase',{
model: { type: MyModel },
query: {
softDelete: false,
},
});
Swagger.setParams([...metadata, ...queryParamsMeta], this.getManyProjects);
}
If the constructor approach does not work for you. Then probably your controller has scope: REQUEST. So controller instance is not created while application initialisation. In this case, you can have custom method inside a controller, like
initSwagger() {
const metadata = Swagger.getParams(this.getManyProjects);
const queryParamsMeta = Swagger.createQueryParamsMeta('getManyBase',{
model: { type: MyModel },
query: {
softDelete: false,
},
});
Swagger.setParams([...metadata, ...queryParamsMeta], this.getManyProjects);
}
then in your main entrypoint file you can write:
app.get(YourController).initSwagger();
It will do the trick
Related
I'm using Relay Modern (compat). I have a fragment that contains a field that has one argument, but I can't find a way of passing the variable value from the parent component:
// MyFragmentComponent.jsx
class MyFragmentComponent extends Component {...}
const fragments = {
employee: graphql`
fragment MyFragmentComponent_employee on Employee {
hoursWorked(includeOvertime: $includeOvertime)
dob
fullName
id
}
`,
}
export default Relay.createFragmentContainer(MyFragmentComponent, fragments)
It will end up saying $includeOvertime is not defined. The context where this component is being rendered looks like this:
// MyRootComponent.jsx
class MyRootComponent extends Component {
render() {
const { employee } = this.props
const includeOvertime = //... value is available here
return (
<div>
<MyFragmentComponent employee={employee} />
</div>
)
}
}
const query = graphql`
query MyRootComponentQuery($employeeId: String!) {
employee(id: $employeeId) {
fullName
...MyFragmentComponent_employee
}
}
`
export default MyUtils.createQueryRenderer(MyRootComponent, query) // this just returns a QueryRenderer
With relay classic you would pass variables this way:
....
employee(id: $employeeId) {
fullName
${MyFragmentComponent.getFragment('employee', variables)}
}
How can I achieve the same with relay modern?
Using #argumentDefinitions and #arguments directives seems to be the way to go. In relay versions before 1.4.0 graphql.experimental had to be used instead of graphql.
In the fragment definition:
const fragments = {
employee: graphql`
fragment MyFragmentComponent_employee on Employee
#argumentDefinitions(includeOvertime: { type: "Boolean", defaultValue: false }) {
hoursWorked(includeOvertime: $includeOvertime)
dob
fullName
id
}
`,
}
If you want the argument to be required:
#argumentDefinitions(includeOvertime: { type: "Boolean!" })
In the parent component you should specify the arguments for the fragment like this:
const query = graphql`
query MyRootComponentQuery($employeeId: String!, $includeOvertime: Boolean) {
employee(id: $employeeId) {
fullName
...MyFragmentComponent_employee #arguments(includeOvertime: $includeOvertime)
}
}
`
In this page in the official relay docs there is an example of directives for defining/passing arguments.
UPDATE:
Since relay version 1.4.0 graphql.experimental was deprecated and now all the features are supported by the regular graphql tag.
UPDATE:
In relay version 1.5.0 graphql.experimental was removed.
I'm trying to access provided / injected values from a mixin in VueJS. I can see those values from any component but not from the mixin. Is what I'm attempting possible?
https://jsfiddle.net/frang/c6c7kqhp/2/1
let myMixin = {
inject: ['myDependency'],
created: function() {
console.log('in mixin', this.myDependency)
}
}
Vue.component('my-component', {
inject: ['myDependency'],
created: function() {
console.log('in component', this.myDependency)
}
})
new Vue({
el: '#example',
provide() {
return {
myDependency: 'here is my value'
}
},
mixins: [myMixin]
})
The issue is that you are trying to inject the myDependency property in the same Vue instance that you are providing it.
Vue instances that specify a provide property give their child components access to that value via inject. But, you cannot inject the provided value on the same instance.
You need to use the mixin in a child component:
Vue.component('my-component', {
mixin: ['myMixin'],
created: function() {
console.log('in component', this.myDependency)
}
})
Here's a working fiddle.
I work in durandal project and use breeze entities.
In my project, I need to create client entity, and on the creating, give initialValues.
Normally, whant you want to give initialValues to new entity, you pass it to createEntity function.
For example:
dataContext.createEntity('employee', {age:40, city:'OurCity'});
So you get new empty instance of employee with default data for age and city.
I want to do it with entity type that contain complexFields.
But it doesn't work.
My entity is client-entity.
Here is the code:
addFormType(store);
function addFormType(store) {
store.addEntityType({
shortName: "FormDTO",
autoGeneratedKeyType: AutoGeneratedKeyType.Identity,
dataProperties: {
key: {//auto primary key. numeratorA and Code cannot be key, becose for new records thier aren't unique
dataType: DataType.Int32, isNullable: false, isPartOfKey: true
}
TaxYear: {
dataType: DataType.String, validators: [Validator.required({ message: 'דרוש' })]
},
Unit_A: {
name: "FormUnit_A",
complexTypeName: 'FormUnit_A:#'
}
}
});
store.registerEntityTypeCtor("FormDTO", null, FormInit);
}
function FormInit(entity) {
validationHelper.initializer(entity);
}
addFormUnit_AType(store);
function addFormUnit_AType(store) {
store.addEntityType({
shortName: "FormUnit_A",
isComplexType: true,
dataProperties: {
CompanyName: {
dataType: DataType.String
},
CompanyAddress: {
dataType: DataType.String
}
}
});
store.registerEntityTypeCtor("FormUnit_A", null, null);
}
I tried to initial it by the follwing rows:
var defaultData = {
TaxYear:0,
Unit_A:{
CompanyName:'ourCompany',
CompanyAddress:'Zar 200 OurCity'
}
};
clientManager.createEntity('FormDTO', defaultData);
But it throws exception: "Object doesn't support property or method 'getProperty'"
I tried also to pass an One-layer object with all of the properties:
var defaultData = {
TaxYear:0,
CompanyName:'ourCompany',
CompanyAddress:'Zar 200 OurCity'
};
clientManager.createEntity('FormDTO', defaultData);
But it throws exception:Object doesn't support property or method 'CompanyName'
So what is the correct way to create-entity with initialValues whan entity contain complex type?
Based of what is working in your project it sounds like you are using something like a camelCase strategy for naming your client side properties. If that is not the case please excuse this answer.
If that is the case then why aren't you using camelCased properties when creating your complex types? Seems simple enough -
var defaultData = {
taxYear:0,
unit_A:{
companyName:'ourCompany',
companyAddress:'Zar 200 OurCity'
}
};
clientManager.createEntity('FormDTO', defaultData);
I am trying to create a modal that will tell the user their submission was successfully submitted. This works fairly well, but the only problem is I have to declare each of my properties and assign it a value, then in the Json method I have accept all those parameters then do something with them. Is there any way to do this with a ViewModel? Or any otherway that this can be done using a ViewModel?
controller:
public Json Send(string var1, string var2)
{
...
if(valid)
return new Json(true, JsonRequestBehavior.AllowGet);
else
return new Json(false, JsonRequestBehavior.AllowGet);
}
javascript:
function submitData() {
$.ajax({
url: "/Report/Send",
type: "POST",
dataType: "json",
data: { var1 = Model.var1, var2 = Model.var2... },
success: function (data) {
if(data) {
showDialog();
}
else {
$("#errorDiv").load('Report/Error/');
}
},
error: function (somefunction) { }
});
}
Yes, create a ViewModel POCO class:
var myJsonResult = new { result: true };
return Json(myJsonResult);
You can also use a strongly typed ViewModel and return that:
var myJsonResult = new CustomResult { result: true };
return Json(myJsonResult);
Then just check that property on the class in your success function:
success: function (data) {
if(data.result) {
showDialog();
}
else if(!data.result) {
$("#errorDiv").load('Report/Error/');
}
},
EDIT:
You might also want to look at jquery's .serialize() method:
data: $("#myForm").serialize()
This will be useful if you bind your ViewModel to form elements and need to post them back to the server.
I started using knockout.js and i really like it.
I use ASP.Net mvc , jQuery and knockout.js
My question is this:
lets say i have a management screen of a user, the user is my view model
inside the user i want an array of permissions
my user viewModel:
var userViewModelClass = function () {
var self = this;
ko.mapping.fromJS({
ID: "",
permissions: []
}, {}, self);
}
now.. if i do an ajax request to the server and get a JSON back i user the mapping plugin, and everything goes as expected
but... now i want my rendered permissions list to have an action like delete.
so i will need a permission object and then the array of permissions will be an array of permission objects. but how do i do that? how will the mapping plugin know that the object returned to him from the server in an array is actually on object like this one:
function permission() {
var self = this;
this.delete = function () {
};
ko.mapping.fromJS({
name: "",
level: ""
}, {}, self);
}
that's my first part of the question.
the second part:
lets say i got the model with an array of all permissions and they are all of this permission object. now i want each delete button in my view to be bind the the delete function inside the permission object.
using:
data-bind="click: delete"
what is the best implementation for a delete function? i thought about something like: makeing an ajax call to the server which will actually delete the permission from the user. then if the call succeeds remove the current permission from the observable array, then the view will update...
is that a good practice?
thanks!
First part. You need to use mapping options. In your userViewModelClass do this.
var userViewModelClass = function () {
var self = this;
ko.mapping.fromJS({
ID: "",
permissions: []
}, {
permissions: {
create: function(options) {
return new permission(options.data);
}
}
}, self);
}
And modify your permission object like so
function permission(config) {
var self = this;
this.delete = function () {
};
ko.mapping.fromJS($.extend({
name: "",
level: ""
}, config), {}, self);
}
Note I added the extend in so that your default structure will remain and be overwritten by incoming data.
Second part of your question. One possible way would be to pass a reference to the parent in your constructor. So the above mapping options would become
permissions: {
create: function(options) {
return new permission(options.data, self);
}
}
Then your delete could be something like.
this.delete = function () {
$.ajax(deleteurl, yourdata, function(result) {
// success
parent.permissions.remove(self);
}, function() {
// failure
display error message
}
};
EDIT
Alternate way as discussed in comments.
var userViewModelClass = function () {
var self = this;
ko.mapping.fromJS({
ID: "",
permissions: []
}, {
permissions: {
create: function(options) {
return new permission(options.data);
}
}
}, self);
this.delete = function(permission) {
self.permissions.remove(permission);
};
}
data-bind="click: $parent.delete"
Hope this helps.