Software Architect at Genzeon Corporation in Malvern, Pennsylvania, Microsoft .NET MVP, Husband, Dad and Geek.
7415 stories
·
22 followers

How to create dynamic menu and page title with Angular Material and CLI

1 Share

Adding Material Design to an Angular CLI project is relatively simple; Connecting your routed page components to a menu with navigation and bookmarking is a little more complex. The solution has a common pattern you can follow using built in angular router and some custom route inspection code. Continuing from a previous article to add Angular CLI to a Visual Studio project that created a blank project shell, we will create a routed application with a Material design appearance. The steps shown also work in Webstorm, VS Code, and any other IDE with NPM support you use for Angular projects today.

The project organization

Some simple projects may be fine just adding a few components to the AppModule and have a completed app, but business scale apps will include multiple application areas. They may be connected by a common app menu, or by accessing functions within each component. I refer to each of these application areas a ‘page component’, which in reality is just a normal component except that it is responsible for the whole content area of the page. This application will consist of 3 main page components

Each page component will be contained within a module with routing. The navigation component included at the top of each page component will read the routing to build the menu. You can also add other menu items, such as for linking outside the SPA into another umbrella site.

Prerequisites

See the previous article if you are working in a Visual Studio project. This article will work for anyone in other editors as well. I vary between WebStorm and Visual Studio 2015 community and Visual Studio 2017 professional.

Ensure NPM, node, and Angular CLI are installed. Open the command prompt and ensure npm and the cli commands are available in your path. just type ‘npm’ and enter to get the help output to verify npm is available, and then ‘ng’ and enter to see the angular cli help and verify it is available for use. I am using the current latest version of each, NPM version 3.10.8, node 6.10.2, and Angular CLI version 1.0.0.

You’ll see the “ng g” command referenced frequently below, this is just an alias for “ng generate”. You can type “g” or “generate”, whichever puts your mind in the right place. The “ng –help” output tells you the alias for each command. I will only use the alias for ‘generate’ below to make it easier to read the commands, since ‘ng g m” and “ng g c” and “ng g s” may be a little too cryptic.

The lines of console commands will start with “C:\…\”. The three dots aren’t in the actual console, I’ve cut the line length down so you can read the commands. Your console will show your full path.

Creating page component routes with Angular CLI

Its easy to create a new component and module following the style guide best practices, plus the command hooks up the newly created components to the right module. Start by creating a page component module. For detailed help type the “ng help” + enter command.

C:\...\candor-sample-ng-cli\src\app>ng g module trip --flat false --routing
installing module
  create src\app\trip\trip-routing.module.ts
  create src\app\trip\trip.module.ts

This command names the module ‘trip’, sets flat to false so that a directory is created for the module, and the routing switch adds the routing module. be aware of the folder where you run this command, as that folder will be the root under which your files are created. This only creates/modifies the files listed in the output, so as you can see this does not add the module to the AppModule.

Now that we have a module for this application area, lets create a component for the page. We’re going to organize the trip module components under the trip folder, so first switch to that directory then run the generate component command.

C:\...\candor-sample-ng-cli\src\app>cd trip

C:\...\candor-sample-ng-cli\src\app\trip>ng g component trip-page
installing component
  create src\app\trip\trip-page\trip-page.component.scss
  create src\app\trip\trip-page\trip-page.component.html
  create src\app\trip\trip-page\trip-page.component.spec.ts
  create src\app\trip\trip-page\trip-page.component.ts
  update src\app\trip\trip.module.ts

This command added the newly generated component to the trip module. It does this by traversing up the folder tree to the nearest folder containing a module, then adds itself to that module. The folder you run CLI commands in matters. You can skip the module import with the ‘skip-import’ option if you so choose.

Building a menu service

Our page components are all going to render a menu for app routes so the user can navigate between app components. Wouldn’t it be nice if the app just knew what modules we had and added them to the menu automatically in a predictable way? Well, it is easy to do just that. Our project already has node module “@angular/router”, added when we generated the project with routing enabled. See the prior article for how we arrived at this point.

Start by creating a ‘service’ using the ng generate command.

C:\...\candor-sample-ng-cli\src\app>ng g service app-toolbar --flat false
installing service
  create src\app\app-toolbar\app-toolbar.service.spec.ts
  create src\app\app-toolbar\app-toolbar.service.ts
  WARNING Service is generated but not provided, it must be provided to be used

The service name is ‘app-toolbar’ but generates the typescript class name of “AppToolbarService”. It’s recommended to generate file names in all lower case with dashes separating words, and CLI will fix that for you when defining the class names. The ‘flat’ switch is set to false to ensure a directory is created.

We left off the ‘module’ flag which would have set the module to ‘provide the service’ in. The output tells us that much, but what can we do about it? The warning gave us a clue, lets edit the AppModule and provide the service. Why the AppModule? I’ve planned ahead and know which component is going to host our toolbar, which will be the AppComponent. If we were going to use it directly in one of the Trip components then we would provide it there.

// src/app/app.module.ts
...
import { AppComponent } from './app.component';
import { AppToolbarService } from './app-toolbar/app-toolbar.service';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        ...
    ],
    providers: [AppToolbarService],
    bootstrap: [AppComponent]
})
export class AppModule { }

The toolbar service implementation

The toolbar service implementation should expose the menu items from the router and keep track of the active menu item as it changes when the user navigates. Todd Motto has a great article on the details (see references below). I’ve extended it a little bit to add an option for a material design icon name for each menu item.

// src/app/app-toolbar/app-toolbar.service.ts
import { Injectable } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';

export class MenuItem {
    path: string;
    title: string;
    icon?: string;
}

@Injectable()
export class AppToolbarService {
    activeMenuItem$: Observable<MenuItem>;

    constructor(private router: Router, private titleService: Title) {
        this.activeMenuItem$ = this.router.events
            .filter(e => e instanceof NavigationEnd)
            .map(_ => this.router.routerState.root)
            .map(route => {
                let active = this.lastRouteWithMenuItem(route.root);
                this.titleService.setTitle(active.title);
                return active;
            });
    }
    getMenuItems(): MenuItem[] {
        return this.router.config
            .filter(route => route.data && route.data.title) //only add a menu item for routes with a title set.
            .map(route => {
                return {
                    path: route.path,
                    title: route.data.title,
                    icon: route.data.icon
                };
            });
    }

    private lastRouteWithMenuItem(route: ActivatedRoute): MenuItem {
        let lastMenu = undefined;
        do { lastMenu = this.extractMenu(route) || lastMenu; }
        while ((route = route.firstChild));
        return lastMenu;
    }
    private extractMenu(route: ActivatedRoute): MenuItem {
        let cfg = route.routeConfig;
        return cfg && cfg.data && cfg.data.title
            ? { path: cfg.path, title: cfg.data.title, icon: cfg.data.icon }
            : undefined
    }
}

At this point no routes define a title attribute, so none will appear in the menu. So let’s update the Trip routing module to set a title. Most of this file was generated, so all we need to change is the route definition at the top.

// src/app/trip/trip-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { TripPageComponent } from './trip-page/trip-page.component';

const routes: Routes = [{
    path: 'trip',
    component: TripPageComponent,
    data: {
        title: 'Trip Finder'
    }
}];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class TripRoutingModule { }

With just one menu item, ordering code isn’t needed, but how can that be added later when more routes are added? The order of routes is predictable based on the order angular router finds the routes. The order angular router finds your routes is based on order of definition in your AppModule. So the simple way to set ordering is to change the order routes are specified. An alternative would be to add ordering information, similar to how ‘title’ and ‘icon’ was added and then order them in the AppToolbarService after filter but before map. For now I’ll stick to import ordering to control menu order.

 //app.module.ts
// typescript imports not shown, see full source for details.
@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        //omitted unrelated modules
        AppCommonModule,
        AppRoutingModule,
        TripModule,
        TripRoutingModule,
        //Future: LocationModule,
        //Future: LocationRoutingModule,
        //Future: PersonModule,
        //Future: PersonRoutingModule,
        RouterModule.forRoot([{
            path: '', redirectTo: '/trip', pathMatch: 'full'
        }])
    ],
    providers: [AppToolbarService],
    bootstrap: [AppComponent]
})
export class AppModule { }

Here the app component puts the trip component first in the menu, then a comment indicates that location module and then person module will be next. We haven’t created these other modules yet in this article, but you can find them in the example project. The last import initializes the RouterModule while setting the default path to redirect to the trip module. The redirect is an optional step since we have no welcome page and instead we’ll just show the trip finder page.

The next step is to use this menu service in our layout to create a menu.

Building a Material design layout

At NgConf 2017 Elad Bezalel created a great set of instructions for a basic angular material layout (see references below). Elad’s quickstart covers the basics of Angular Material and how to put it in your project. The only problem is that it is based on a slightly out of date version of Material before the MaterialModule was obsolete. Lets fix that, and while we are at it lets use that sidenav to create a menu of our page components.

Create a module of Material components

The MaterialModule is obsolete so that you don’t add components you don’t need to your project, unnecessarily increasing the size of your application. They will be adding more components over time, inevitably you won’t be using them all. However, including each one only where it is needed will still result in code duplication, since many of the modules you will consider core to your application. This step is optional, you can instead add each of the components you need to the modules that use them.

C:\...\candor-sample-ng-cli\src\app>ng g module app-common --flat false
installing module
  create src\app\app-common\app-common.module.ts

You’ll need to import this generated module into others that use the components in it. In this project that means the app module, which will contain the side nav and the trip component which will use cards, inputs and more. Just add the AppCommonModule to the NgModule imports, not the declarations or exports.

// src/app/trip/trip.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AppCommonModule } from '../app-common/app-common.module';

import { TripRoutingModule } from './trip-routing.module';
import { TripPageComponent } from './trip-page/trip-page.component';

@NgModule({
  imports: [
    CommonModule,
    AppCommonModule,
    TripRoutingModule
  ],
  declarations: [TripPageComponent],
  exports: [
      TripPageComponent
  ]
})
export class TripModule { }

Make the same addition to AppModule. See the example repo for details.

Within the AppCommonModule lets add in all the layout components we will need in our app. Keep the list as short as possible. This list shown here does not include all available component modules, but may still be too many for some apps. Add each you will use to the module imports and exports. I’m adding some material modules and the angular flex-layout module.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { //only import the portions you will use to optimize build (MaterialModule to include all is deprecated)
      MdCoreModule,
      MdButtonModule,
      MdCardModule,
      MdIconModule,
      MdMenuModule,
      MdRippleModule,
      MdSidenavModule,
      MdToolbarModule,
      //... add others you need
} from '@angular/material';
import { FlexLayoutModule } from '@angular/flex-layout';

@NgModule({
  imports: [
      CommonModule,
      MdCoreModule,
      MdButtonModule,
      MdCardModule,
      MdIconModule,
      MdMenuModule,
      MdRippleModule,
      MdSidenavModule,
      MdToolbarModule,
      FlexLayoutModule,
      //... add others you need
  ],
  declarations: [],
  exports: [
      MdCoreModule,
      MdButtonModule,
      MdCardModule,
      MdIconModule,
      MdMenuModule,
      MdRippleModule,
      MdSidenavModule,
      MdToolbarModule,
      FlexLayoutModule,
      //... add others you need
  ]
})
export class AppCommonModule { }

Defining the layout with menu

This app will structure the master layout wrapping all the page modules in the app component along with a router-outlet with the content of each page component.

The basic structure of the page will be a main content area with a sidenav to the left side that for now is always open. A sidenav needs to be contained inside a sidenav container. The whole thing is placed inside an fxLayout with fxFlex to make it take up the full screen height.

 //app.component.html
<div fxLayout="column" fxFlex>
    <md-sidenav-container fxFlex>
        <md-sidenav mode="side" opened>
            ...
        </md-sidenav>
        ...
        <router-outlet></router-outlet>
    </md-sidenav-container> 
</div>

Now lets add to this by allowing the user to close the side nav and add a toolbar. This project will add a toolbar to the sidenav and another to the main content area. It will appear as a single toolbar but with a different color in the sidenav area. You can opt to only include a toolbar in the main area if you prefer. I use the toolbar in the side nav to show the app icon and name, but you can do that in the main content area. Try a few variations to see which you prefer.

 //app.component.html
<div fxLayout="column" fxFlex>
    <md-sidenav-container fxFlex>
        <md-sidenav #mainSideNav mode="side" opened>
            ...
        </md-sidenav>
        <md-toolbar color="primary">
            <button md-icon-button (click)="mainSideNav.toggle()">
                <md-icon *ngIf="mainSideNav.opened">chevron_left</md-icon>
                <md-icon *ngIf="!mainSideNav.opened">menu</md-icon>
            </button>
            <!--<md-icon *ngIf="navItem.icon">{{navItem.icon}}</md-icon>-->
            {{(activeMenuItem$ | async)?.title}}
        </md-toolbar>
        <router-outlet></router-outlet>
    </md-sidenav-container> 
</div>

The above layout added a button to the main area toolbar to close and open the sidenav. This is done using a template variable #mainSideNav, not defined in the component typescript. The button click triggers the toggle function defined on the sidenav component, again not a function in the component typescript.

The view does show the active menu item as defined in the component typescript. It pulls the title from the active menu item, and since it is an observable as you will see below this will update anytime the router switches to another active route. The icon is stubbed in, but not yet used.

Now for the final version, lets add the menu items to the main sidenav.

 //app.component.html
<div fxLayout="column" fxFlex>
    <md-sidenav-container fxFlex>
        <md-sidenav #mainSideNav mode="side" opened>
            <md-toolbar>
                <img src="../assets/logo.png" style="height:80%"> {{appName}}
            </md-toolbar>
            <md-nav-list>
                <a *ngFor="let navItem of mainMenuItems" 
                   md-list-item
                   md-ripple
                   [style.position]="'relative'"
                   routerLinkActive="selected"
                   [routerLink]="[navItem.path]">
                    <!--<md-icon *ngIf="navItem.icon">{{navItem.icon}}</md-icon>-->
                    <span>{{navItem.title}}</span>
                </a>
            </md-nav-list>
        </md-sidenav>
        <md-toolbar color="primary">
            <button md-icon-button (click)="mainSideNav.toggle()">
                <md-icon *ngIf="mainSideNav.opened">chevron_left</md-icon>
                <md-icon *ngIf="!mainSideNav.opened">menu</md-icon>
            </button>
            <!--<md-icon *ngIf="navItem.icon">{{navItem.icon}}</md-icon>-->
            {{(activeMenuItem$ | async)?.title}}
        </md-toolbar>
        <router-outlet></router-outlet>
    </md-sidenav-container> 
</div>

The template above uses some variables to be defined by the component, ‘appName’, ‘mainMenuItems’, and ‘activeMenuItem$’.

 //app.component.ts
import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { AppToolbarService, MenuItem } from './app-toolbar/app-toolbar.service';

@Component({
  selector: 'body',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
    appName = 'Ride Finder';
    mainMenuItems;
    activeMenuItem$: Observable<MenuItem>;

    constructor(private toolbarService: AppToolbarService) {
        this.mainMenuItems = this.toolbarService.getMenuItems();
        this.activeMenuItem$ = this.toolbarService.activeMenuItem$;
    }
}

We’ve injected the AppToolbarService and called the public members to get the menu items (one time call), and gathered a reference to the observable of the active menu item. Since activeMenuItem is an observable I named it with a dollar sign at the end, a common convention for observable variables. This convention is not required, but is recommended.

For our trip component template, let’s add what will be the main content area when that route is active. The design should be responsive, so for now I’ll create a layout mimicking a grid layout with a main card and an aside card to the right, then when the screen is small the aside card will jump to below.

 //trip-page.component.html
<div class="content" fxLayout="row" fxLayout.sm="column" fxLayout.xs="column" fxLayoutGap="16px">
    <md-card fxFlex="80">
        trip component works!
    </md-card>

    <md-card fxFlex fxLayout="column" fxLayoutGap="14px">
        aside
    </md-card>
</div>

The main content div defines an fxLayout of row so the default flow will show the 2 cards side by side. On the extra small (fxLayout.xs) and small (fxLayout.sm) layout width screens the fxLayout will toggle to ‘column’ so the cards stack. The two cards are defined inside this div with the first card defining a percentage width it will take (when in row layout). The fxLayoutGap attributes define a space between cards.

Wrap Up

This sample contains a single routed page with material design layouts and a dynamic menu and page title. In the example repo there are also two other routes in the menu. Each of the three page components are defined with similar Angular CLI commands. Future steps within one module would be to add more components for the various sections of a page such as search form, search results, and an item detail. You can see the general idea by looking at the other non-CLI, systemJS based web project in the same repository.

References

Example project repository
https://github.com/michael-lang/sample-ng2-mvc

Todd Motto: Dynamic page titles in Angular 2 with router events
https://toddmotto.com/dynamic-page-titles-angular-2-router-events

Elad Bezalel: Quick Starter Repository for Angular Material 2
https://github.com/EladBezalel/material2-start

Read the whole story
alvinashcraft
6 hours ago
reply
West Grove, PA
Share this story
Delete

Turn your Postman Collection into a Microsoft integration

2 Shares

If you've ever wanted to automate more pieces of your life, but didn't have the time or the will to build out a custom app, there's a powerful tool that will allow you to build a custom integration with minimal development.

Similar to the trigger-based, conditional logic of IFTTT or Zapier, Microsoft Flow is a service that allows you automate workflows with the applications and tools that you're already using.

Microsoft Flow focuses on enterprise tools and the free service provides rate-limited access to a broad set of services, such as Slack and Intercom.  The premium subscription tier provides more bells and whistles and access to a wider set of services, such as Salesforce and Zendesk.

So how does it work? For Postman users, uploading a Postman Collection to Microsoft Flow automatically generates your custom API description. From there, Microsoft Flow allows you to add new actions and conditional logic to automate your personal and professional workflows to sync files, collect data, and receive notifications.

Asavari Tayal, Program Manager at Microsoft, shows us how to create a Microsoft Flow connector from a Postman Collection.


Turn your Postman Collection into a Microsoft integration

by Asavari Tayal, Program Manager at Microsoft

Do you own a Postman Collection for your HTTP APIs? Now you can use this collection to build a 'Connector' for Microsoft Flow and Logic Apps.

Microsoft Flow  is a cloud-based service that makes it simple to automate common tasks and business processes across your applications and services, such as Office 365, Slack, Dropbox, SalesForce.com, Dynamics 365 and many more. 

Azure Logic Apps enables you to build powerful workflows and integration solutions in Azure.

What is a Connector

A connector is a proxy or a wrapper around your API that allows the underlying web app to talk to Flow and Logic Apps. It provides a way for users to connect their own account and leverage a set of pre-built Triggers and Actions for their apps and workflows.

By being a part of our growing connector family (currently at 110+), you can enable your users to automate common tasks and build workflows in combination with other social and business applications. View our current list of connectors here

How to build a Connector

In this post, we will use the example of the Asana API to demonstrate how to build an Asana Connector starting from a Postman Collection.

You can try this yourself by downloading the postman collection located here.  

The first step to build a Connector is to build a Custom API. Think of a Custom API as a private Connector. i.e. – it’s only visible to you and the users you share it with within your tenant.

1. Import your Postman Collection

To get started, head over to the Microsoft Flow website and navigate to the Custom API wizard.

From the Custom API wizard in Flow, select Upload Postman collection V1. Browse to your saved collection and import it.

This collection will get parsed and the schema from your Postman calls will be used to define the metadata for your connector. You can now choose to  edit the connector icon and description.

2. Setup authentication 

To specify the authentication type, switch to the Security tab and pick OAuth2.0. If you’re using one of the supported authentication types in Postman, this information will be automatically populated.

Enter the Client id and Client secret for your OAuth2 app, along with other information to support the authentication flow.

3. Define actions

After completing the security information, switch to the Definition tab to view your connector’s operations. Note – These have been pre-populated using the Postman collection you uploaded earlier.

For each operation, you’ll see a Summary, Description, Operation ID and Visibility.  These properties are used to modify the end-user experience for your connector. You can change these values at any time.

Besides the UI properties, each operation also includes information about the API call including the HTTP Verb, URL, path and query parameters, header and the body of the request. It also includes a schema for the response expected from the service. In the Asana example, these were auto-generated from your Postman collection.

You can now edit the details of existing actions and even add new actions. For each new action, you will need to provide a sample request and response along with general details about the operation.

Finally, click on Create API in the top right corner to finish creating the Custom API. 

Use your connector to build Flows and publish Templates

The operations you defined in the Custom API will now show up as actions in the Flow designer.

Pick any one of these actions to build a simple workflow like the one shown in the figure below.

This Flow creates a new task in your Asana account when a new issue is assigned to you in your Github account. Please note that in order to use a connector in Flow, you will need to make a connection to authenticate your account with the underlying service. 

To publish the Custom API as a Connector, submit a nomination hereMicrosoft will contact you with further details about submitting your connector.

Once your connector has been published, you can create flows and submit templates to the gallery featuring your connector. These templates will be available for all users to directly consume or customize further, by connecting their own accounts.

You now have an exciting workflow solution for your users! 

For more information, please refer to these articles:

Tell us how you’re using the Postman x Microsoft Flow integration by tweeting at us at @postmanclient and @MicrosoftFlow.

This is a guest post by Asavari Tayal, Program Manager at Microsoft.

Read the whole story
sbanwart
6 hours ago
reply
Akron, OH
alvinashcraft
7 hours ago
reply
West Grove, PA
Share this story
Delete

Visual Studio Code C/C++ extension April 2017 Update

1 Share

Earlier today we shipped the April 2017 update to the C/C++ extension for Visual Studio Code. We are excited to introduce the following new features in this update:

  • Error Squiggles
  • Quick Info
  • Go to Declaration
  • Bash on Windows debugging support

The original blog post has been updated with these changes. If you have this extension installed already, Visual Studio Code sends a notification for the update and installs the update for you automatically. If you haven’t installed it before, download the C/C++ extension for Visual Studio Code to try it out.

1-download

Error Squiggles and Quick Info

Enabling the features

In this update, we’re shipping Error Squiggles and Quick Info as “experimental features”. What this means is that they are turned on by default only for those using VSCode Insiders, and off by default for anyone else. You can enable or disable the features by toggling the setting in the settings.json file (File->Preferences->Settings). In the settings file, search for “intellisense” to locate the C_Cpp.intelliSenseEngine setting, and set it to “Default” to enable the new IntelliSense Engine (see the following screenshot). “Default” will become the true default for everyone when these features exit their experimental state. 🙂

2-intellisense-engine

The “C_cpp.errorSquiggles” setting in the same file allows turning on or off the squiggle feature when the default IntelliSense engine is used.

We encourage you to turn on the features, try them out, and send us feedback so we can further polish these features and turn them on by default soon.

Error Squiggles

A while back we enabled showing error squiggles for the #include statements. This update adds support for showing squiggles under any program element, including variables, keywords, and braces, if a workspace exists. In other words, squiggles are not enabled when only single files are open.

For example, in the following screenshot, Vector3 has a red squiggly underline, indicating this type can’t be found in the specified include paths.

3-quick-action

Clicking on Vector3 in the code, you will see a light bulb on the left side of the line. The “Add include path to settings” menu on the light bulb will take you to the c_cpp_properties.json file in which you can specify the include paths for IntelliSense. If the c_cpp_properties.json file does not already exist, it will be created and populated with the following default include paths:

  • On Windows, we default to the workspace root, the VC include path if Visual Studio 2017 or 2015 is installed, and the latest Windows SDK if found.
  • On Linux, we default to the workspace root, the highest version of the includes found in /usr/include/c++, 64-bit specific headers if they are present, and headers found under /usr/lib/clang if present.
  • On Mac, we default to the workspace root and the Xcode default toolchain if present or the same paths as Linux if Xcode is not found.

You can add, remove, or modify the paths in the includePath setting to fit your scenario. In this example, I added another path (highlighted with the red underline) for the IntelliSense engine to look for types.

4-include-paths

Note that there’s a newly-added “path” setting under “browse”, which is used by the tag parser for performing fuzzy search results. The “includePath” setting, which was formerly used by the tag parser, now controls the include paths for the new IntelliSense engine. On opening any existing c_cpp_properties.json files, the value in the “includePath” is automatically copied into the “browse.path” setting.

You can also configure the “defines” setting in the c_cpp_properties.json file to define preprocessor symbols.

Now if I save the change in the json file and switch back to the previous header file, the types are now resolved and the red squiggles are gone.

Quick Info

Quick Info enables viewing the type information or function’s signature when hovering the mouse cursor over a variable or a function. In this extension, this used to be performed by the tag parser, which provides quick but fuzzy results – sometimes inaccurate. With the new IntelliSense engine, we can provide more accurate results for local and global variables, functions, and symbols. In the following screenshot, hovering over the local variable “it” displays its accurate type information.

5-quick-info

Go to Declaration

With this extension, you can already perform “Go to Definition” (F12) on variables or functions to open the document where the object is defined. This update added “Go to Declaration” (Ctrl+F12) for navigating to the file where the object is declared. To use this feature, simply right click on any variable or function and select “Go to Declaration” from the menu.

In this example in the following screenshot, I selected “Text.DrawString” function and clicked on “Go to Declaration”.

6-go-to-declaration

In the next screenshot, you can see that the “TextRenderer.h” file is open and the two DrawString function declarations are being highlighted.

7-show-declaration

Bash on Windows debugging support

With the release of Windows 10 Creators Update, you are now able to use VSCode and this extension to debug your Windows Subsystem for Linux (WSL) Bash on Ubuntu projects. You can use VSCode to write code on Windows, and debug through bash.exe to the Bash on Windows layer. Please see these instructions on how to use VSCode C/C++ extension to debug Windows 10’s Subsystem for Linux.

Tell us what you think

Download the C/C++ extension for Visual Studio Code, try it out and let us know what you think. File issues and suggestions on GitHub. If you haven’t already provided us feedback, please take this quick survey to help shape this extension for your needs.

Read the whole story
alvinashcraft
7 hours ago
reply
West Grove, PA
Share this story
Delete

Thank You, Linda Rising

1 Share
I recently looked back at the impact that Linda Rising has had on my career and life, and I wanted to express my gratitude for that.

I first heard Linda on the Hanselminutes podcast back in 2013: The Agile Mindset with Linda Rising. Listening to her describe the agile mindset compared to the fixed mindset really opened my eyes. I immediately watched a recorded keynote called "The Power of the Agile Mindset" (the link I had to that is sadly no longer working).

The short version: With the fixed mindset, we have a certain potential that we can reach for any particular area. This leads to "I'm good at this; I'm not good at that." With the agile (or growth) mindset, we can get better at whatever we put effort into. This leads to "I can learn to be better at this."

This clarified some of my observations and led to quite a bit of self-reflection. (Here's the long version if you're interested: Fixed vs. Agile Mindset.)

Initial Realizations about Others
When I heard this concept, certain things immediately started to make sense. For example, there was a development team where the managers refused to invest in the developers. Instead, they were constantly looking for the process or tool that would make the team successful. This always frustrated me to watch, but I realized that the management had a fixed mindset toward their team: "Our developers are as good as they are going to be, so we need to look for solutions elsewhere."

I've always had the opposite opinion about developers. And fortunately the team that I joined when I was a brand new developer believed that as well. With the agile mindset, there wasn't anything that we couldn't learn. We were constantly building each other up and making each other better. I know that my situation was fairly unique, but I really wish that all junior developers could have such a productive environment.

And since I'm a speaker, coach, educator, Developer Betterer, I obviously have this mindset toward the developers that I'm teaching. And I don't think of it as teaching most of the time, I think of it as helping people past the hurdles that I had trouble with when I was learning a particular topic.

Initial Realizations about Myself
The real eye-opening moment, though, was when I started to reflect on myself. I found that I had the agile mindset in some areas and the fixed mindset in others. For example, when it came to technology, I was pretty confident that I could learn whatever I put my mind to. But that wasn't true of all areas of my life.

When it came to things like music, I thought of myself as "not a musical person". On reflection, I came to realize that I had never put any real effort into it.

I had a few more realizations that you can read about in my original article: Fixed Mindset vs. Agile Mindset.

Changing My World
I decided to get over my hurdle with music. So, I bought a banjo in January 2015. And I set about to learn to play it. And I made progress.

But more importantly, I was able to use the banjo as an object lesson for others.

Learning Something New
First, I did something I never would have done before: I played a musical instrument badly in front of other people. There was a time in my life when I would never think about playing for others unless I new the piece perfectly. But now I'm okay with showing that I'm not an expert and that learning takes time: You Aren't Instantly Awesome, and That's Okay.

This has been a great way to talk about learning in our industry. As developers, we're constantly having to learn new things. And it's really easy to feel inadequate when there are so many people who already know this new thing. But we all have to start somewhere, and everyone has to go through that same learning process.

Getting Better
The good news is that I tracked my progress with the banjo. And I did see actual progress: You Aren't Instantly Awesome, But You Can Get Better with Practice.

What this proved to me is that I am a musical person. And I can get better when I put the effort into it.

Getting Help
Another thing I learned is that once I dropped the fear of being imperfect, I was no longer afraid of asking for help from the experts. Again, specifically with the banjo, I was able to get help from a former professional player and from a professional music instructor. (Read more about that here: Don't Be Afraid to Show What You Don't Know.)

In the technical world, I've never been afraid to ask for help. But by going through this experience, it reinforced the idea that there's nothing to be ashamed of when you don't know something. I like to try to figure things out on my own, but I have no trouble asking for help when I get stuck. And this has led to some great learning experiences (particularly from the functional programming community which is so willing to help out).

Unfortunately, our industry has a general fear of showing weakness. I'm trying to promote that fact that no one knows everything, we all have our strengths and weaknesses, and we all have to start somewhere. I would love to see that fear disappear.

Giving Help
The extension of this is that I'm not afraid of giving help when asked. I don't think that I've ever really had this problem personally, but there are some known problems with this in our industry.

So I encourage other people to help the people they can. And there is always someone who knows less than we do, someone who has not had the same experiences that we've had, someone who has not yet struggled through the things we've struggled through. So whatever level we're at, we have something to share. Please, Help Those Behind You.

Thank You, Linda
I can trace a lot of this back to hearing Linda Rising talk about the ability that we all have to learn and improve when we put effort into it.

Thank you, Linda, for opening my eyes to a topic that I've been able to use to better myself and better those around me. I knew that this had an impact on me, but looking back, I see just how much of an impact it has had. Over the course of 3-1/2 years, the idea of learning and getting better at whatever I put my mind and energy into has given me opportunities and helped me make the world a better place.
Read the whole story
alvinashcraft
7 hours ago
reply
West Grove, PA
Share this story
Delete

Ionic 3: New Features In TypeScript 2.1 & 2.2

2 Shares

Ionic 3.0 was released a couple weeks ago and it comes packed with a lot of new features, one of them is that it supports TypeScript 2.2.

In this post we'll have a look at some of the new features that have been introduced with TypeScript 2.1 and 2.2, so you'll be able to use them in your new Ionic 3 apps.

For a complete list of all TypeScript features, have a look here.

Untyped imports

A TypeScript 2.1 feature that is very much appreciated is the ability to import a third-party module that doesn't have a TypeScript Declaration File.

So an import like the one below would cause an error in older versions of TypeScript if there are no TypeScript Declarations installed for PouchDB.

import * as PouchDB from 'pouchdb';  

In the Ionic 2 starter templates there was a workaround introduced for this in the declarations.d.ts file, with the following line of code:

declare module '*';  

This line of code basically tells TypeScript that it shouldn't check if any module you're importing is actually available in your app. This can be very annoying if you're prone to typos and your editor doesn't notify you straight away that there is an error there.

So now in Ionic 3 apps we don't need this workaround anymore and you should remove this line if it's still included in your app.

Object Spread and Rest

These are new features in TypeScript 2.1 and are implemented following the ES2017 specification for Object Spread/Rest and are similar to Array Spread/Rest in ES2015.

Spread

Spread creates a shallow copy of an object. We can easily add new properties to the copy or override copied properties with a new value.

let original = { a: 1, b: 2  };

// copy original
let copy1 = { ...original };

 // copy original and add c
let copy2 = { ...original, c: 3 };

// copy original and override x 
let copy3 = { ...original, a: 0 };  

// copy original and override with properties from another
let another = { b: 20, c: 30 };  
let copy4 = { ...original, ...another };  

Keep in mind that this is a shallow copy, so if the original object has properties that reference other objects, only the references will be copied.

Rest

You could already destructure an object in older versions of TypeScript but now you can use the rest syntax in destructuring as well.

let obj = { a: 1, b: 2, c: 3, d: 4 };  
let { a, b, ...remainder } = obj;

// a will be 1
// b will be 2
// remainder will be { c: 3, d: 4 } 

Async-Await

Async-Await was introduced in earlier versions of TypeScript, but could only be used with transpilation to ES2015 until TypeScript 2.1 which supports the use of it in applications that transpile to ES5.

Async-await uses Promises under the hood. It's only a different (easier to read) syntax for using Promises.

Let's say we are using the Ionic Platform service in our app to check when it's ready loading and we want to log to the console when that happens.

We'll create a wrapper method that calls platform.ready() which returns a Promise. Without async-await, it would look like this:

checkPlatformReady() {  
  return this.platform.ready()
    .then(readySource => {
      console.log('Platform ready:', readySource);
      return readySource;
    });
}

With async-await, the code will change to this, both implementations of checkPlatformReady will have a return type of Promise<string>:

async checkPlatformReady() {  
  let readySource = await this.platform.ready();
  console.log('Platform ready:', readySource);
  return readySource;
}

You can only use async-await with Promises, so if you want to use it with Observables, you'll have to call .toPromise() on the Observable.

Better checking for null/undefined

And lastly I wanted to mention this feature although it's not really usable in Ionic 3 apps at the moment because of an issue with Angular 4 that will hopefully be solved soon.

In TypeScript 2.2 the compiler will show you an error when you're trying to use nullable variables in the following situations (list taken from the release notes):

  • If either operand of a + operator is nullable, and neither operand is of type any or string.
  • If either operand of a -, , *, /, %, <<, >>, >>>, &, |, or ^ operator is nullable.
  • If either operand of a <, >, <=, >=, or in operator is nullable.
  • If the right operand of an instanceof operator is nullable.
  • If the operand of a +, -, ~, ++, or -- unary operator is nullable.

The compiler will only check this if you have strictNullChecks set to true in tsconfig.json.

So, for example, if we have a function that takes three parameters where the last one is optional and tries to multiply them, it will show an error during compilation.

function multiply(first: number, second: number, third?: number) {  
   return first + second + third;
}

// the line below will result in NaN because the third parameter is undefined, 
// but now you will get an error at compile time
multiply(1, 2);  

You can turn on strictNullChecks in your Ionic 3 app, but Angular 4 is not supporting it yet, so you'll see a bunch of errors during compilation. The ES5 code will still be generated, but it's not really a great developers experience.

Follow the status of this issue in Angular 4 here.

There are many more features in TypeScript 2.1 and 2.2, but I can't cover them all in this blog post. Here is a complete list all new features. If you don't feel confident in your TypeScript skills, sign up for my upcoming course below!

Read the whole story
sbanwart
7 hours ago
reply
Akron, OH
alvinashcraft
7 hours ago
reply
West Grove, PA
Share this story
Delete

The week in .NET – Happy Birthday .NET with Chris Sells, free ASP.NET Core book, We are the Dwarves

2 Shares

Previous posts:

Happy birthday .NET with Chris Sells

In February, we threw a big .NET birthday bash with Microsoft Alumni and product teams. We caught up with Chris Sells who is currently a Product Manager at Google, and before that a Program Manager at Microsoft. Chris has been part of the .NET developer community since the beginning and he tells us a few great stories in this fun interview.

Book of the week: ASP.NET Core succinctly, by Simone Chiaretta and Ugo Lattenzi

In ASP.NET Core Succinctly, seasoned authors Simone Chiaretta and Ugo Lattanzi update you on all the advances provided by Microsoft’s landmark framework. Learn the foundations of the library, understand the new versions of ASP.NET MVC and Web API, and you’ll have everything you need to build .NET web applications on Windows, Mac, and Linux.

ASP.NET Core Succinctly

You can get the book now, for free!

Game of the Week: We are the Dwarves

We are the Dwarves is a real-time tactical adventure game. Set in a world where the Dwarven stars are slowly dying, you must guide three astronauts through their expedition to find a new star in the depths of the Endless Stone. Each dwarf has individual abilities and skill trees, letting you customize to your play style. Pay close attention to the hostile environment as you lay out your tactical strategy when fighting your enemies.

We are the Dwarves

We are the Dwarves was created by Whale Rock Games using C# and Unity. It is available Steam for Windows, Mac and Linux, Xbox One and PlayStation 4.

Meetup of the week: Productivity in Visual Studio 2017 with GitHub, .NET Core, and Docker in San Francisco, CA

The Bay .NET user group has a two-part meeting on Thursday, April 27 at 6:30PM featuring excellent speakers: Sara Ford will talk about the GitHub extension for Visual Studio 2017, and Beth Massi will tell you all about .NET Core, Docker, and microservices.

.NET

ASP.NET

C#

F#

The F# weekly is taking a break this week, but F# links will be back next week.

Xamarin

Azure

UWP

Data

Game Development

And this is it for this week!

Contribute to the week in .NET

As always, this weekly post couldn’t exist without community contributions, and I’d like to thank all those who sent links and tips. The F# section is provided by Phillip Carter, the gaming section by Stacey Haffner, the Xamarin section by Dan Rigby, and the UWP section by Michael Crump.

You can participate too. Did you write a great blog post, or just read one? Do you want everyone to know about an amazing new contribution or a useful library? Did you make or play a great game built on .NET?
We’d love to hear from you, and feature your contributions on future posts:

This week’s post (and future posts) also contains news I first read on The ASP.NET Community Standup, on Weekly Xamarin, on F# weekly, and on The Morning Brew.

Read the whole story
sbanwart
7 hours ago
reply
Akron, OH
alvinashcraft
8 hours ago
reply
West Grove, PA
Share this story
Delete
Next Page of Stories