Make column section width relative in D365 Business Central cloud - dynamics-365

I am a seasoned MS CRM developer with very little experience in BC/AL development.
I have a current CRM client that also uses BC and has I small request I am trying to assist with.
When adding new column sections in a record, the client wants the column section widths to be relative so that the users don't have to scroll down to view the additional column section.
example below:
I have succeeded connecting VS Code to BC cloud tenant and have validated the connection with a simple "Hello World" function after deployed.
May someone point me in the right direction on how to approach the AL I need to use?
Regards.

I don't think there is an easy solution for what you are searching for.
You can take a look at "Grid Layout" for pages, but grid layouts are not that relative.
https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-arrange-fields-in-rows-and-columns-using-gridlayout-control
With Grid Layouts you can define columns and put your fields in these columns.
How i understand you want to change an existing page (item page) so you could try somthing like this:
pageextension 50100 ItemCardExtension extends "Item Card"
{
layout
{
modify(Item)
{
Visible = false;
}
addafter(Item)
{
grid(MyGrid)
{
group("Column1")
{
// Add fields here
}
group("Column2")
{
// Add fields here
}
group("Column3")
{
// Add fields here
}
}
}
}
}
But there will be some additional Problems, if you add all fields you need to implemnt all the exitsing Code (triggers on page level) by yourself (personally i wouldn't do this). Maybe you could try and add only one field by code for each group and add all other fields from the client with personalisation, but i never tried that.

Related

Post data to custom AL field in Business Central

I am trying to create an API call to add data into a custom field that was created on the Sales Order page using AL Extensions. The issue is when I try to do the api call through postman, I am getting "The Property "propertyName" does not exist on type 'Microsoft.NAV.salesOrder'". First of all, I don't even know if the API allows for this, so is it even possible? And secondly, if it is possible, is there a certain way to set up the API call or the Field through the AL Extension?
tableextension 50100 "AddProjectIdToSalesOrder" extends "Sales Header"
{
fields
{
field(50100; "CrmProjectId"; Guid)
{
Caption = 'Crm Project Id';
DataClassification = OrganizationIdentifiableInformation;
}
}
}
pageextension 50100 "AddProjectIdToSalesOrder" extends "Sales Order"
{
layout
{
addlast(General)
{
field("CRM Project Id"; Rec.CrmProjectId)
{
ApplicationArea = all;
ToolTip = 'The Guid of the related Project Record in the CRM environment';
}
}
}
}
This is how I am setting up the field with the AL extension, and for the post call, I am just creating a new Sales Order with a post and the body looks like:
{
"customerNumber" : "10000",
"CrmProjectId" : "random-guid"
}
And the error is "Bad Request": "The property 'CrmProjectId' does not exist on type 'Microsoft.NAV.salesOrder'. Make sure to only use property names that are defined by the type." Any help would be appreciated.
The Sales Order API is a separate page. It is not equivalent to the Sales Order page so you have to modify the API to accomplish what you want.
However the standard API's provided by Microsoft can't be extended.
You are left with two options:
Make a copy of the standard Sales Order API (this involves making a copy of all the linked APIs as well e.g. the Sales Line API).
Create a new API page with the single purpose of updating your new field. Then you would use the standard Sales Order API to create the Sales Order and then update CrmProjectId with a second call to your custom API page.

How are arguments added to GraphQL, do they need to be defined before?

Hi Everyone I am just trying to learn graphql as I am using Gatsby. I want to know does each field in graphql take an argument or does it need to be defined somehow before. So for example if you visit this link graphql search results
https://graphql.org/swapi-graphql?query=%7B%0A%09allPeople%20%7B%0A%09%20%20people%20%7B%0A%09%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20birthYear%0A%20%20%20%20%20%20eyeColor%0A%09%20%20%7D%0A%09%7D%0A%7D%0A
If i wanted to limit people by eye color how would I do that. In the docs it seems easy as you would just do something like people(eyecolor: 'brown') but that doesn't seem possible. Am I missing something? I basically want to do a SQL style search for all people where eye color is brown.
Thanks.
Arguments need to be defined in the schema and implemented in the resolver. If you're consuming a 3rd party API (like the link you provided), you're limited to their schema. You can tell by looking at their schema (by clicking Docs on the right side of the page) which fields take arguments. For example, person takes id and personID arguments:
people doesn't take any arguments, as seen in the schema:
If you're building your own schema, you can add arguments to any field, and when you implement the resolver for that field you can use the arguments for logic in that resolver.
If you're working with a schema that you don't control, you'll have to add filtering on the frontend:
const {people} = data.allPeople;
const brownEyedPeople = people.filter(({eyeColor}) => eyeColor === 'brown');
When you start developing in Gatsby and actually pull your data into Gatsby, there will be a filter query option that automatically becomes available in the query arguments.
https://www.gatsbyjs.org/docs/graphql-reference/#filter
You can expect to be able to filter your people by eyeColor by using the below query:
{
allPeople(filter: { eyeColor: { eq: "brown" } }) {
edges {
node {
id
name
birthYear
eyeColor
}
}
}
}

Creating a filtered search based on different parameters

i need to create a filtered search based on different paramnters chosen by a user. So, for example, my app is a property app. I want them to be able to define the county, town, max,min bedrooms ect from a dropdown list and press search, and this returns all the properties that match the criteria.
How do I go about doing this? I can't find any tutorials online, but maybe I'm not phrasing it right.
Here is an image of what I'm after from a UI point of view.
https://imgur.com/a/YEEqt
The following is an easy to go solution considering your experience.
Create a new controller or a method in an existing one.
First create a simple form (method GET) in blade that will return predefined values from simple hidden fields
Create a new GET route in which the form must be submitted and link it to the controller method that you created
In your controller method get the submitted form data from your request, make the correct queries and return the blade template file that contains the form with the results
Modify blade template to show results
Finally replace the hidden fields with selects drop-downs and modify your controller in order to populate them
You can make the form submission process and the select drop-down fields population asynchronous but based on your experience with Laravel it should be hard. Following the steps above will do your job.
Always take a look to the official documentation. You will ge a lot of help from there.
You can try like this for filter options in your controller
public function filter(Request $request, Property $property)
{
$property = $property->newQuery();
// Search for a property based on country
if ($request->has('country')) {
return $property->where('country', $request->input('country'));
}
// Search for a property based on their area.
if ($request->has('areas')) {
return $property->where('areas', $request->input('areas'));
}
// Search for a property based on max_price
if ($request->has('max_price')) {
return $property->where('price','<=', $request->input('max_price'));
}
// Continue for all of the filters.
return $property->get();
}
For more info refer the link

Apollo/React mutating two related tables

Say I have two tables, one containing products and the other containing prices.
In Graphql the query might look like this:
option {
id
price {
id
optionID
price
date
}
description
}
I present the user with a single form (in React) where they can enter the product detail and price at the same time.
When they submit the form I need to create an entry in the "product" table and then create a related entry in the "price" table.
I'm very new to Graphql, and React for that matter, and am finding it a steep learning curve and have been following an Apollo tutorial and reading docs but so far the solution to this task is remaining a mystery!
Could someone put me out of my misery and give me, or point me in the direction of, the simplest example of handling the mutations necessary for this?
Long story short, that's something that should actually be handled by your server if you want to optimize for as few requests as possible.
Problem: The issue here is that you have a dependency. You need the product to be created first and then with that product's ID, relate that to a new price.
Solution: The best way to implement this on the server is by adding another field to Product in your mutation input that allows you to input the details for Price as well in the same request input. This is called a "nested create" on Scaphold.
For example:
// Mutation
mutation CreateProduct ($input: CreateProductInput!) {
createProduct(input: $input) {
changedProduct {
id
name
price {
id
amount
}
}
}
}
// Variables
{
input: {
name: "My First Product",
price: {
amount: 1000
}
}
}
Then, on the server, you can parse out the price object in your resolver arguments and create the new price object while creating the product. Meanwhile, you can also relate them in one go on the server as well.
Hope this helps!

In Meteor, where do I model my business rules?

Beginner question : I've worked through the Try Meteor tutorial. I've got fields in my HTML doc, backed by helper functions that reference collections, and BOOM --> the fields are updated when the data changes in the DB.
With the "Hide completed" checkbox, I've also seen data-binding to a session variable. The state of the checkbox is stored in the Session object by an event handler and BOOM --> the list view is updated "automatically" by its helper when this value changes. It seems a little odd to be assigning to a session object in a single page application.
Through all this, my js assigns nothing in global scope, I've created no objects, and I've mostly seen just pipeline code, getting values from one spot to another. The little conditional logic is sprayed about wherever it is needed.
THE QUESTION... Now I want to construct a model of my business data in javascript, modelling my business rules, and then bind html fields to this model. For example, I want to model a user, giving it an isVeryBusy property, and a rule that sets isVeryBusy=true if noTasks > 5. I want the property and the rule to be isolated in a "pure" business object, away from helpers, events, and the meteor user object. I want these business objects available everywhere, so I could make a restriction, say, to not assign tasks to users who are very busy, enforced on the server. I might also want a display rule to only display the first 100 chars of other peoples tasks if a user isVeryBusy. Where is the right place to create this user object, and how do I bind to it from my HTML?
You can (and probably should) use any package which allows you to attach a Schema to your models.
Have a look at:
https://github.com/aldeed/meteor-collection2
https://github.com/aldeed/meteor-simple-schema
By using a schema you can define fields, which are calculated based on other fields, see the autoValue property: https://github.com/aldeed/meteor-collection2#autovalue
Then you can do something like this:
// Schema definition of User
{
...,
isVeryBusy: {
type: Boolean,
autoValue: function() {
return this.tasks.length > 5;
}
},
...
}
For all your basic questions, I can strongly recommend to read the DiscoverMeteor Book (https://www.discovermeteor.com/). You can read it in like 1-2 days and it will explain all those basic questions in a really comprehensible way.
Best Regards,
There is a very good package to implement the solution you are looking for. It is created by David Burles and it's called "meteor-collection-helper". Here it the atmosphere link:
You should check the link to see the examples presented there but according to the description you could implement some of the functionality you mentioned like this:
// Define the collections
Clients = new Mongo.Collection('clients');
Tasks = new Mongo.Collection('tasks');
// Define the Clients collection helpers
Clients.helpers({
isVeryBusy: function(){
return this.tasks.length > 5;
}
});
// Now we can call it either on the client or on the server
if (Meteor.isClient){
var client = Clients.findOne({_id: 123});
if ( client.isVeryBusy() ) runSomeCode();
}
// Of course you can use them inside a Meteor Method.
Meteor.methods({
addTaskToClient: function(id, task){
var client = Clients.findOne({_id: id});
if (!client.isVeryBusy()){
task._client = id;
Tasks.insert(task, function(err, _id){
Clients.update({_id: client._id}, { $addToSet: { tasks: _id } });
});
}
}
});
// You can also refer to other collections inside the helpers
Tasks.helpers({
client: function(){
return Clients.findOne({_id: this._client});
}
});
You can see that inside the helper the context is the document transformed with all the methods you provided. Since Collections are ussually available to both the client and the server, you can access this functionality everywhere.
I hope this helps.

Resources