Turnkey Angular notes

This is a document created during Turnkey for Angular and Bootstrap development and describes the built in functionality and how it can be used. Please check back for updates!

Angular implementation starting point

Please read this for a background to TurnKey-driven viewmodels and actions

http://www.new.capableobjects.com/2011/02/27/wecpofgettingtothebottomofthelineofbusinessapplication/

Form / Viewmodel types

Seek form

The seek form that from nothing can search objects in persistent storage and show them in a list

Browser form

This is a special case of the Seek form in that it doesn’t require a search string, it shows all object of a class.

Document form

The form has a root object provided by the action showing the form (viewmodel).

Form variations

A common use case is when a viewmodel don’t require a root object, but instead uses a singleton object filter or show objects related to the logged in user.

Vocabulary

Lists can be in “single-row” or “multiple-row” mode. That is they can have only one row selected (stored in vCurrent) or multiple rows selected (stored in vSelected).

Default behaviour (mixed list)

Loading shows an animated “loading image” on the top.

Left menu moves along with scrolling down.

Styling and CSS

Adding a text in “Style ref” (or an OCL-expression) to the viewmodel in designer, will add that string as a class on the controls tag in the html.

Build in styles for header h1, h2, h3, h4 works with default bootstrap. Example: “h3” as style, will add class=”h3” to the control tag.

If you add an section of { } the part within the braces will be used as formatstring, the rest as style reference. For example, when formatting dates and time, {short} will show date and time in compact format.

Picture style

Images are rendered with “img-responsive” set. If you override in CSS, img-responsive is ignored.

Pictures NOT in grids

Has style class “vmImage” set. Add CSS to set size

Setting picture size in grids

Has style class “vmImageInGrid” set. Add CSS to set size

To set style for a specific control, or group of controls, add style in the designer in “Style ref”. The content of “Style ref” will be added to an ng-class tag in the HTML. Don’t forget to add the style in your CSS.

Name use for style and css-classes

  • Name “Style” is used to render HTML as attribute style=”<attribute value>”
  • Name “CssClass” is used to render HTML as an added class with the name of the attribute value

Example

In OCL for the Style attribute, use ‘background-color:#’ + cell.ColourValue.toString(‘X6’) + ‘;’ for sending a colour value to a cell. You can of course also use a HTML colour name.

You can use ‘warning’ or ‘info’ for CssClass and it will colour using Bootstrap default CSS classes.

Table styling

Note! Breaking changes made. If you’ve already implemented using this guide before, look below for a few required changes

You can style tables in different ways: The column, The row or a single Cell

Add style to the viewmodel attribute (for name and data of the column) and it will style the entire column. (“Style ref:” in the designer)

Add a string attribute to the viewmodel used for a table with the name “Style” or “CssClass” to style the entire row. You usually make the resulting string dependent on the data for the cell for different colouring.

Add a string attribute to the viewmodel used for a table with the name <Column name>_Style or <Column name>_CssClass to style the column of the rendered row, i.e. the Cell. You usually make the resulting string dependent on the data for the cell for different colouring.

Pivot tables

After looking thru a lot of ready-made pivot tables, we decided to use the build in table of HTML/Bootstrap. Why? Because a lot of the features added by third party pivot/grid add-ins can easily be handled on the server within the model. Things like searching, sorting, filtering, paginating. And if we do it within the model and viewmodels, we can move the functionality to other platforms with a minimum of extra work. In addition, operations like search and filter, often isn’t as straight forward as initially thought, requiring something not in the grid/pivot, and then the third-party grid component comes short. Still, there’s nothing preventing the use of third-party add-ins for a grid, just let the framework provide the data.

What we do need for a grid/pivot (only pivot from now) is a way to render Cells with different content in all positions. We want the actions to work on cells, not entire rows.

Look at this page http://mdrivenwordpress.azurewebsites.net/2013/06/10/custom-controls-in-viewmodel-aided-views/ and scroll down to “A slightly more complex sample” for a background on the thinking of creating a pivot from your model.

Pattern

Following that pattern with a different naming conversion to better fit how HTML, BS and Angular names things, we end up with;

image

From the example;

CurrentMonthView is a single object, a root of sorts.

The viewmodel “Row” is the one you put on the page where you want your pivot.

The other viewmodels, you position outside the screen, for example at a negative Row value. They will not be rendered, but provide data.

If you compare this with the other Pivot component, there’s a important difference! You need to provide the rows IN ORDER and you need to provide ALL CELLS on every row. Why? Because Angular data binding iterating your arrays can’t “go back” to paint, i.e. it’s not a paint in any order type of display, we have to keep within the confines of HTML and BS.

Because of this, there no Y-position in “Row” and there’s not an X-position in the “ColumnHeader”. There is however a RowID in both “Row” and “AllCellsList”, so the client can find the right group of cells for the row, and then lay them out in “ColOrder”. In effect we’re assuming that the order of column headers and row cells appears in the correct order.

Creating the structure described

You can simply use a viewmodel and use OCL expressions to add objects to the list. Probably objects of different types, but as long as your viewmodelclass’s attributes evaluates to match the pattern, it will work.

Another way to add more structure is to have modelled classes, either transient or persistent, that organizes your data into a structure that matches the pattern.

Here’s an example of transient class (the gray ones) with persistent classes “supporting” them. This is the same example as above.

 

image

As you can see the MonthViewCell class has been subclassed. Why? To make the logic for different cell types easier to maintain and to make it easier to place actions for each cell type.

On the subclasses, you add OCL to the derived attributes, each working with it’s own type of information.

Tagged values

Then add tagged value like this;

CurrentMonthView

image

ColumnHeader

image

Row

No tagged values.

AllCellsList

image

Most of these are, as you can see when you compare with the example, the names you picked for the different fields in your viewmodel. They all default to the same name (without Attr) if you don’t set them.

Pay extra attention to “RowIdAttr”. You have to provide this attribute in both the Row viewmodelclass and in the AllDellsList viewmodelclass. This attribute’s value is what bind the cells to the row. It has to be unique in the list on screen, not globally.

Not all are required, FormatAttr, CssClassAttr, StyleAttr and ValueFormatFilterName are optional.

Styling

ValueFormatFilterName  is the most interesting, because it allows you to put Javascript on your client to parse the value you send. You can then make it as complex as you like. The default ValueFormatFilter accepts a JSON object and converts it to a real typed value on the client. Why is this important? Because your cells are different, and if you can’t send a date as a JS date value, your client can’t format it correctly.

In the example above, all values are included in a JSON “frame”. In the case of a date, the value OCL is self.Day.Date.formatDateTime(‘yyyy-MM-ddTHH:mm:ssZ’), which is a valid JSON date as a string. This will be handled by the client and formatted using the Format attribute with an OCL ‘dd, EEE’, which is a short date format, “day and month”.

If you create your own Angular filter you can render any complex values into a cell.

Actions

You place actions, either class or viewmodel, on the AllCellsList or the class that makes up the AllCellsList.

Date-formatting

You set date and time format in the Style attribute enclosed in { }.

For example, for dates and time, {short} will show date and time in compact format. The default date format is {shortDate}. Please refer to the Angular guide for formatting dates https://docs.angularjs.org/api/ng/filter/date

The date and time format are automatically localized depending on the browser.

Save-state

When an attribute or link changes, the ECO-space state is changed which is signaled in the GUI with Save, Undo, Redo and Cancel buttons in the left menu. In addition to this, a “Save and Cancel-bar” is displayed at the top when in “small mode”

Each viewmodel holds a separate save-context.

If not saved, the user can’t go back and forward with the browser buttons without asking “Save or Cancel?”, preventing abandoned save-states.

If creating a new object and showing that in a viewmodel, pressing Cancel shows a confirm dialog. If Ok, cancels changes and navigates back to the previous page.

Ways to navigate (GUI use cases)

Select MainMenu in large and small mode and selecting an item.

This loads or reloads the Angular “app” with the new page.

Select an item in the visible left menu

Executes the action picked.

If this navigates to a new page, that Angular-page is loaded out of band and inserted in the DOM.

Left menu button is clicked and item in the visible left menu is selected

This has the exact same effect as when the menu is visible. It hides the menu, even if the action doesn’t navigate.

Navigation use-cases

  • Using model action to navigate with unsaved data Yes, ask first.
  • Browser forward in history with unsaved data No
  • Browser backward in history with unsaved data No
  • Leave to another page with unsaved data Warning (not possible to stop)
  • Close page with unsaved data Warning (not possible to stop)
  • Cancel on newly created object Automatic back navigation
  • Own deletion of root object in view Inform and then automatic back (automatic?)
  • Others deletion of root object in view Inform and then automatic back

Selecting a row in “single row” mode

For a master-detail use-case, i.e. letting vCurrent in one list affect another list. Set “Always show actions” on the viewmodel class that should be selectable without prompting the pop-up menu.This will create a master-detail style operation. If you don’t want any actions visible – opt them out.

Creating a Wizard (one ViewModel)

Here a Wizard means a viewmodel that changes based on state

HOW? _____________

Creating a Wizard (multiple ViewModels)

Here a Wizard means several viewmodels linked with actions

HOW? _____________

Modal windows

Modal windows shares save-context with it “parent”, non-modal viewmodel. The modal window is not part of the back-forward navigation scheme.

Navigating in a modal window

  • Pressing OK or Cancel button will return success and failure to the action opening the modal window.
  • Actions shown in a modal window works in two ways
    • They act without navigation, i.e. act on the objects with the save-context
    • If they navigate, it will open a new browser tab and “spawn” a new browser-session.

Modal windows uses the same Angular-mechanism as the pop-up menu for actions.

Actions

Click on lists

Single-row handling

Default for lists is to show a pop-up menu or perform the default action if it’s the only one. Usually this is for a “Show”-action navigating to the object clicked.

If you select “Always show actions” for a ViewModel class in the designer (i.e. a list), it will be rendered in “select one” mode and with the actions for the current row in the left menu. Clicking on the list/row will NOT show the pop-up menu or perform the default action if it’s the only one.

If the list don’t have any actions “opted-in”, the list should also be rendered in”select one” mode.

Multi-row handling

You can turn on multi-select for lists by adding the tag “MultiSelect” with the value True (no quotes) on the viewmodel class.

  1. Select viewmodel class, click on “TV and Attributes”.
  2. Add the MultiSelect value to the Value Store.
  3. Add the Value Store value to the viewmodel.

This will make selecting and deselecting individual rows possible and update the vSelected variable.

You then make actions acting on the vSelected collection in the server action.

Dragging and DragDrop actions

Drag-Drop angular code is generated for lists by adding the tags DragSource or DropTarget with the value True (no quotes) on the viewmodel class.

Swipe action

To activate an action to trigger when the user swipes, add tagged values on the viewmodel class. The value should be the action name you want to execute. For different swipe actions, add;

  • Left-swipe: Tag SwipeLeft
  • Right-swipe: Tag SwipeLeft

Swipe both ways: Tag SwipeLeft and SwipeRight

Data-validation

At the bottom of the screen, info, warning and error messages are shown.

They don’t have any effect on navigation as of today.

Language and internationalization

Don’t do any conversion in your viewmodel. If you do, you will send a string to the client, making client formatting impossible.

I.e. you viewmodel attribute should evaluate to a DateTime.

File BLOBS

Tag “BlobDownloadLink” on an attribute will render a download link for the attribute. Add Attribute “FileName” next to blob in the viewmodel class if you wish to databind to that FileName attribute.

Tag “DataIsLink” on a string attribute will render the string asi an link-URL.

This entry was posted in AngularJS, Javascript, MDrivenTurnkey, Turnkey and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*