How would you retrieve dropdown items from an observable in #rxweb/reactive-dynamic-forms ?
how do you inject service in FormControlConfig subclass? shared code here https://stackblitz.com/edit/angular-bs5yqt-nmzcwj
For injecting custom services into the dynamic form control source model you have to pass the respective service into the argument of model configuration.
Step 1
Create a Service according to your need, I am creating fake ConfigService.
import { HttpClient} from "#angular/common/http"
import { Injectable } from "#angular/core"
#Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
configUrl = 'assets/config.json';
getConfig() {
return this.http.get(this.configUrl);
}
}
Step 2
Let's create a Model, which is extended with FormControlConfig for async source binding.
import { FormControlConfig } from "#rxweb/reactive-dynamic-forms"
import { ConfigService } from "./config.service"
export class SourceAsyncConditionalModel extends FormControlConfig{
constructor(fieldConfig: { [key: string]: any }, public controlsConfig: { [key: string]: FormControlConfig },notificationId:number,private configService:ConfigService){
super(fieldConfig,controlsConfig,notificationId);
}
filter() {
let promise = new Promise<any>((resolve, reject) => {
/// call the service
if(this.configService)
this.configService.getConfig();
});
}
}
If you see the above the code where I have defined four parameters. The first three parameters are used in FormControlControl and the fourth parameter we can use in the model instance.
Step 3
Now, we have to pass the parameter with respective model. See the below code :
this.dynamicFormConfiguration = {
controlConfigModels: [{ modelName: 'sourceAsync', model: SourceAsyncConditionalModel,arguments:[this.configService] }],
}
this.dynamicFormBuildConfig = this.formBuilder.formGroup(this.serverData, this.dynamicFormConfiguration);
Here is the working Example
Related
I have a backstage instance in which i am using AAD login in which backstage is passing some scope like "user.read offline_access etc" value, i want to add few more keys like "Clendar.ReadWrite". is there any way to do that in backstage.
I am trying to pass ./default values in scope key. I have searched a lot for possible solutions but couldn't get any of it
If I didn't get it wrong, do you want to transform the values created for the User entity?
This documentation may help, if applicable.
The following provides an example of each kind of transformer
import * as MicrosoftGraph from '#microsoft/microsoft-graph-types';
import {
defaultGroupTransformer,
defaultUserTransformer,
defaultOrganizationTransformer,
} from '#backstage/plugin-catalog-backend-module-msgraph';
import { GroupEntity, UserEntity } from '#backstage/catalog-model';
// This group transformer completely replaces the built in logic with custom logic.
export async function myGroupTransformer(
group: MicrosoftGraph.Group,
groupPhoto?: string,
): Promise<GroupEntity | undefined> {
return {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: {
name: group.id!,
annotations: {},
},
spec: {
type: 'aad',
children: [],
},
};
}
// This user transformer makes use of the built in logic, but also sets the description field
export async function myUserTransformer(
graphUser: MicrosoftGraph.User,
userPhoto?: string,
): Promise<UserEntity | undefined> {
const backstageUser = await defaultUserTransformer(graphUser, userPhoto);
if (backstageUser) {
backstageUser.metadata.description = 'Loaded from Azure Active Directory';
}
return backstageUser;
}
// Example organization transformer that removes the organization group completely
export async function myOrganizationTransformer(
graphOrganization: MicrosoftGraph.Organization,
): Promise<GroupEntity | undefined> {
return undefined;
}
I am trying to apply custom sorting to the models; however, using the sort computed property is sorting the models on the initial load of the page but it is not auto-updating the page when more models are entered into the store.
Ember-Source: 4.7.0
Ember-Data: 4.7.3
Ember-CLI: 4.6.0
Ember-CLI-Typescript: 2.4.0
app/models/item.ts:
import Model, { attr } from '#ember-data/model';
export default class Item extends Model {
#attr('string')
declare name: string;
}
// DO NOT DELETE: this is how TypeScript knows how to look up your models.
declare module 'ember-data/types/registries/model' {
export default interface ModelRegistry {
'item': Item;
}
}
app/routes/index.ts:
import Route from '#ember/routing/route';
import { service } from '#ember/service';
import type Store from '#ember-data/store';
export default class Index extends Route {
#service
declare store : Store;
async model(){
return this.store.peekAll('item');
}
}
app/controllers/index.ts:
import Controller from '#ember/controller';
import { sort } from '#ember/object/computed';
import Item from 'sorting-test/models/item';
const sortNumeric = (a: Item, b: Item) => parseInt(a.id, 10) - parseInt(b.id, 10);
export default class Index extends Controller {
#sort("model", sortNumeric)
declare sortedModels: Item[]
}
// DO NOT DELETE: this is how TypeScript knows how to look up your controllers.
declare module '#ember/controller' {
interface Registry {
'index': Index;
}
}
app/templates/index.hbs:
{{#model.length}}:{{this.sortedModels.length}}
tests/acceptance/index-test.ts:
import { module, test } from 'qunit';
import { visit, settled } from '#ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import type Store from '#ember-data/store';
module('Acceptance | index', function (hooks) {
setupApplicationTest(hooks);
test('visiting /', async function (assert) {
const store = this.owner.lookup('service:store') as Store;
await visit('/');
assert.equal(this.element.textContent, '0:0');
store.createRecord('item', {id: '10', name: 'A'});
store.createRecord('item', {id: '2', name: 'B'});
await settled();
assert.equal(this.element.textContent, '2:2');
});
});
Passes the first assertion but the second assertion fails with:
actual: > 2:0
expected: > 2:2
I have tried changing the line #sort("model", sortNumeric) to use different combinations of model.[], model.#each, model.#each.id but none of them seem to have any effect.
How do get the template to auto-update with custom sorting? (and is this a reoccurrence of https://github.com/emberjs/ember.js/issues/19101)?
Change the controller to use a native getter rather than the sort computed property:
import Controller from '#ember/controller';
import Item from 'sorting-test/models/item';
const sortNumeric = (a: Item, b: Item) => parseInt(a.id, 10) - parseInt(b.id, 10);
export default class Index extends Controller {
// Declare the model otherwise typescript raises errors.
declare model: Item[];
get sortedModels(){
// Copy the array otherwise sort will try to re-order it in place and fail.
return this.model.slice().sort(sortNumeric);
}
}
// DO NOT DELETE: this is how TypeScript knows how to look up your controllers.
declare module '#ember/controller' {
interface Registry {
'index': Index;
}
}
I'm trying to implement an extension of typegraphql's createUnionType() function to where I can pass in a class/ObjectType instead of hardcoding, and it will return a union type of both.
What I have so far doesn't work but I feel like it's possible. Could anyone provide any insight? Maybe it's not possible?
typedefs
import { ObjectType, Field, createUnionType, ClassType } from "type-graphql";
#ObjectType()
export default class MutationSuccess {
#Field()
success: boolean = true;
}
// Doesn't work
export const MutationResponse = (objectType: ClassType) => createUnionType({
name: 'MutationResponseType',
types: () => [MutationSuccess, objectType],
})
How I'm trying to use it in my resolver
#Resolver()
export default class RelationResolver {
#Mutation(() => MutationResponse(Relation), { description: 'follow user' })
async follow(
#Arg('relationInput') relationInput: RelationInput
): Promise<Relation | MutationSuccess> {
// do some stuff
}
}
error
UnhandledPromiseRejectionWarning: Error: Cannot determine GraphQL output type for follow
The Relation class need to be decorated with #ObjectType and the union type name has to be unique.
We have a factory which creates types using generic types:
export function GenericResolverFactory(props: FactoryProps) {
#GqlType(`${props.model.name}Response`)
class ModelPaginatedResponse extends ResponseFactory(props.modelClass) {
// you can add more fields here if you need
}
#GqlInputType(`${props.model.name}CreateInput`)
class CreateInput extends CreateInputFactory(props.createInput) { }
#Resolver(_of => props.modelClass, { isAbstract: true })
abstract class GenericResolver {
#Mutation(_returns => props.modelClass, { name: `create${startCaseName}` })
create(#Arg('data') data: CreateInput, #Ctx() _context: UserContext) {
return this.__getService().create(data);
}
}
return ModelResolverClass;
}
For now we have to declare the input args like: Arg('input') input: UpdateInput
As my types are generated using a factory the classes won't be available at (not runtime?). Is there a way to refer to those dynamically generated inputs? Is there a way to do something like: Arg('input') input: resolveType('ProductCreateInput')
Assuming that resolveType returns a class decorated with #InputType and #Fields:
#Arg('input', type => resolveType('ProductCreateInput')) input: ICreateInput`
You just need to provide a runtime value as the second parameter of #Arg decorator
Im trying to load the following sample data to jqgrid(free) using http.get in angular 6.
[{"maker":"Toyota", "model":"Celica"},{ "maker": "Chrysler", "model":"Mondeo"}]
Model Class
export class Model{
maker : string
model : string
}
Component:
...
#Component({...})
export class SampleComponent implements OnInit {
private _sampleService;
columnModel : any[];
models : Model[];
constructor(_sampleService : SampleService) {
this._sampleService = _sampleService;
}
ngOnInit() {
this.columnModel = [{ name: "maker" },{ name: "model" }]
this.models = this._sampleService.getModelList().subscribe(models => this.models = models);
}
ngAfterViewInit() {
(<any>jQuery("#grid")).jqGrid({
colModel: this.columnModel,
data: this.models
});
}
}
Service:
....
#Injectable()
export class SampleService{
constructor(private http : HttpClient){}
getModelList():Observable<Model[]>{
return this.http.get<Model[]>
("http://localhost:8090/myapp/getModel");
}
}
If I do the following, I can see the data in the console.
this.http.get("http://localhost:8090/ducksoup/getModel")
.subscribe(data => {console.log(data)})
But,it is not rendering in the grid. Any help?
You can write your jqxGrid binding code inside of OnInit method, right after you fetch your records and it will show your data on datagrid