From 4bce7bf9097d6d43c67b09fab170f63b157130c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 13 Mar 2020 11:36:25 +0300 Subject: [PATCH 1/2] Added Layout Hooks section. --- .../Customization-User-Interface.md | 82 +++++++++++++++++- docs/en/UI/AspNetCore/Layout-Hooks.md | 3 + docs/en/UI/AspNetCore/Toolbars.md | 3 + ...kstore-google-analytics-view-component.png | Bin 0 -> 30016 bytes 4 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 docs/en/UI/AspNetCore/Layout-Hooks.md create mode 100644 docs/en/UI/AspNetCore/Toolbars.md create mode 100644 docs/en/images/bookstore-google-analytics-view-component.png diff --git a/docs/en/UI/AspNetCore/Customization-User-Interface.md b/docs/en/UI/AspNetCore/Customization-User-Interface.md index a360665c7b..3fc2c0886b 100644 --- a/docs/en/UI/AspNetCore/Customization-User-Interface.md +++ b/docs/en/UI/AspNetCore/Customization-User-Interface.md @@ -299,7 +299,7 @@ Menu contributors are executed whenever need to render the menu. There is alread ### Toolbar Contributors -Toolbar system is used to define toolbars. Modules (or your application) can add items to a toolbar, then the theme renders the toolbar on the layout. +[Toolbar system](Toolbars.md) is used to define toolbars on the user interface. Modules (or your application) can add items to a toolbar, then the theme renders the toolbar on the layout. There is only one standard toolbar (named "Main" - defined as a constant: `StandardToolbars.Main`). For the basic theme, it is rendered as shown below:![bookstore-toolbar-highlighted](../../images/bookstore-toolbar-highlighted.png) @@ -368,10 +368,84 @@ That's all, you will see the notification icon on the toolbar when you run the a `NotificationViewComponent` in this sample simply returns a view without any data. In real life, you probably want to query database (or an HTTP API) to get notifications and pass to the view. If you need, you can add a `JavaScript` or `CSS` file to the global bundle (as described before) for your toolbar item. -### Layouts - -TODO +See the [toolbars document](Toolbars.md) for more about the toolbar system. ### Layout Hooks +[Layout Hooks](Layout-Hooks.md) system allows you to add code at some specific parts of the layout. Given standard hook names are defined by the ABP framework: + +* **"Header.First"** (Defined as a constant: `LayoutHooks.Head.First`): To add code to the beginning in the `head` HTML element. +* **"Header.Last"** (Defined as a constant: `LayoutHooks.Head.Last`): To add code to the end in the `head` HTML element. +* **"Body.First"** (Defined as a constant: `LayoutHooks.Body.First`): To add code to the beginning in the `head` HTML element. +* **"Body.Last"** (Defined as a constant: `LayoutHooks.Body.Last`): To add code to the end in the `head` HTML element. + +All layouts of all themes should implement these hooks. You can then add a view component into any of the hook points. + +#### Example: Add Google Analytics Script + +Assume that you need to add the Google Analytics script to the layout (that will be available for all the pages). + +First, create a view component in your project: + +![bookstore-google-analytics-view-component](../../images/bookstore-google-analytics-view-component.png) + +**NotificationViewComponent.cs** + +````csharp +public class GoogleAnalyticsViewComponent : AbpViewComponent +{ + public IViewComponentResult Invoke() + { + return View("/Pages/Shared/Components/GoogleAnalytics/Default.cshtml"); + } +} +```` + +**Default.cshtml** + +````html + +```` + +Change `UA-xxxxxx-1` with your own code. + +You can then add this component to any of the hook points in the `ConfigureServices` of your module: + +````csharp +Configure(options => +{ + options.Add( + LayoutHooks.Head.Last, //The hook name + typeof(GoogleAnalyticsViewComponent) //The component to add + ); +}); +```` + +Now, the GA code will be inserted in the `head` of the page as the last item. You (or the modules you are using) can add multiple items to the same hook. All of them will be added to the layout. + +The configuration above adds the `GoogleAnalyticsViewComponent` to all layouts. You may want to only add to a specific layout: + +````csharp +Configure(options => +{ + options.Add( + LayoutHooks.Head.Last, + typeof(GoogleAnalyticsViewComponent), + layout: StandardLayouts.Application //The layout to add + ); +}); +```` + +See the layouts section below to learn more about the layout system. + +### Layouts + TODO \ No newline at end of file diff --git a/docs/en/UI/AspNetCore/Layout-Hooks.md b/docs/en/UI/AspNetCore/Layout-Hooks.md new file mode 100644 index 0000000000..49b334c6c0 --- /dev/null +++ b/docs/en/UI/AspNetCore/Layout-Hooks.md @@ -0,0 +1,3 @@ +# Layout Hooks + +TODO \ No newline at end of file diff --git a/docs/en/UI/AspNetCore/Toolbars.md b/docs/en/UI/AspNetCore/Toolbars.md new file mode 100644 index 0000000000..cc3bcd95be --- /dev/null +++ b/docs/en/UI/AspNetCore/Toolbars.md @@ -0,0 +1,3 @@ +# Toolbars + +TODO \ No newline at end of file diff --git a/docs/en/images/bookstore-google-analytics-view-component.png b/docs/en/images/bookstore-google-analytics-view-component.png new file mode 100644 index 0000000000000000000000000000000000000000..e548a00935cacdea120d91f51a2f3ed2312b5b07 GIT binary patch literal 30016 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

Pmgj*J$FWbO#Ylm|q89ldVt5?z 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ℜSpoq)`6V#PlT~VbH zevGJvEzfK1Axe4|C${uKIiN*#h@)uUW1wD$-8!MEXLPfvKlo-3DDP7{Vz=SCU7>)9 zx}ANH1+^YM<B!#I+F%EYto%(k46! zakyD8MkiK7zInc1D}VXH3E@1pq^SdYroBK+ylZ%Ukyd0mx^t(ThGZNE^2Bm|#KmtF zZV?p$`Xx5$^oAl}`Yg^)YI~vSFsQAlK)7>0mn4vT~P8ugx zS#PfkagNk2#yy3J51C?up%*<{0b`0OBM5#f>mM5Z%P9TBCkQIm zvis>0?*^3zfH-;1VvvC=RUvcGlMX=JhI6cBhpg{R56Ih;$bRYtX*^+?HUq3Umm)4I$VTAT#TE(xXngLM zSRLtW-gI3(dRI8$u*FNrZ61b=9Wr1>OR9)IO{rREF~zN+>TJ?sU^6B8!EWI@BO37g zgSo2=PR!20(#Ypw7TlQrge=Uth@N9w7*%2M!#Cojd6FPX0gbGhqG#C%+U!e3sXz&v zNOE#tw zUViC9?|h88o=ES^t@3&9Kk0hBSDu^9t}R(`lJ-=(7wU9bgdWv_n%K0L@ZYWpiYA8p z_HNJ=^Ot*&5V5PVSJxu(-!pWJTWxe~qI#Dl(BPAmWbNod>|PN*LYf}1jEpka^#3L_ z>J1tG?lR4*xY*+pT_f#&Z<)3r`qxM3C?5!{fI_JgM%H@+TpB!@y`did-k44Tf<1x^ z{8X1kV$}w7Ak+5$oykAso;O+M%h>%EO{M+g5aRobD7etCd0cB9q5a0=*aE!b(ar12 zYwmoQ-M4zCYuJAgx%XDPM73uLllqJk7l4ecZoeUNE!}9lJl2_fClA?oSSXgZg_9!< zJipA0Y?`Gxe`ZO07)d=FVhL+xQBF1x(exy5SZ;gKQ ztch?@wrI?s$0F9~{{TJz%F8Ci=mUwIHSVdFA@?C?%ER36bJzok~1FLa5{RVbWHDd0KDzLsn{8BSkc&9XlGJU464rV zc9wsl_09j>D6;bZQ@0!S$hK@=+_C^Jrv%Wop}Eg8 z8zsFWmche-IZ=*No0||35YpQMXnSOQ{07kBX#O?KZk3P6GLrm_1?{nGjo% zj{O1SY-pq*bss2s8vbRzUik#%C)~JV*TIFKA6#HrYvr0ILj~QYH4ZUg4qakrG z$&Vz#DrlHYwgKx@H%(4W`3Cg2Us9L_0cT^io!zPmpre~aSMXASwk?9di)B=kd}szQ zvf}$-aDpjR*T8Jq^b>f?wlk^+r5;mu^W?9F4GJ_0D2M3nfk+odbPoL%lH9GJJn=Zv z^>}-Iv=n(6(Jz2ifw>9omx=O~Z4!^5(ZA0A`tkBs2b zQ?-$vmUg!=u@7jlf@OdI-s@=bL~{ubs^&GH1_DeSW!2>Vm{07_)!bTi`(+^@viFLIqyE5VTvyS? z?0hE0V=>X;nn?UVO@F=;l7h7i&l~~=_Uy}QA{r5{z66m$U%Wu^jq}a3?@HVNZ$<^l MN-9ZIi5Ug_AD_^LUjP6A literal 0 HcmV?d00001 From ecfd34e5953433c7c0f56de5f48883ba5a521ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 13 Mar 2020 11:49:18 +0300 Subject: [PATCH 2/2] Update Customization-User-Interface.md --- .../Customization-User-Interface.md | 59 ++++++++----------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/docs/en/UI/AspNetCore/Customization-User-Interface.md b/docs/en/UI/AspNetCore/Customization-User-Interface.md index 3fc2c0886b..7e49efd602 100644 --- a/docs/en/UI/AspNetCore/Customization-User-Interface.md +++ b/docs/en/UI/AspNetCore/Customization-User-Interface.md @@ -122,19 +122,19 @@ That's all! Make any change in the view and run your application. #### Replacing Page Model Without Inheritance -You don't have to inherit from the original page model class (like done in the previous example). Instead, you can completely re-implement the page yourself. In this case, just derive from `PageModel`, `AbpPageModel` or any suitable base class you need. +You don't have to inherit from the original page model class (like done in the previous example). Instead, you can completely **re-implement** the page yourself. In this case, just derive from `PageModel`, `AbpPageModel` or any suitable base class you need. ## Overriding a View Component -The ABP Framework, pre-built themes and modules define some re-usable view components. These view components can be replaced just like a page described above. +The ABP Framework, pre-built themes and modules define some **re-usable view components**. These view components can be replaced just like a page described above. ### Example -The screenshot below was taken from the basic theme comes with the application startup template. +The screenshot below was taken from the **basic theme** comes with the application startup template. ![bookstore-brand-area-highlighted](../../images/bookstore-brand-area-highlighted.png) -[The basic theme](../../Themes/Basic.md) defines some view components for the layout. For example, the highlighted area with the red rectangle above is called Brand component. You probably want to customize this component by adding your own application logo. Let's see how to do it. +[The basic theme](../../Themes/Basic.md) defines some view components for the layout. For example, the highlighted area with the red rectangle above is called **Brand component**. You probably want to customize this component by adding your **own application logo**. Let's see how to do it. First, create your logo and place under a folder in your web application. We used `wwwroot/logos/bookstore-logo.png` path. Then copy the Brand component's view ([from here](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Brand/Default.cshtml)) from the basic theme files under the `Themes/Basic/Components/Brand` folder. The result should be similar the picture below: @@ -154,21 +154,21 @@ Now, you can run the application to see the result: If you need, you can also replace [the code behind c# class](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Brand/MainNavbarBrandViewComponent.cs) of the component just using the dependency injection system. -## Overriding the Theme +### Overriding the Theme Just as explained above, you can replace any component, layout or c# class of the used theme. See the [theming document](Theming.md) for more information on the theming system. -## Overriding Static Resources +### Overriding Static Resources Overriding a static embedded resource (like JavaScript, Css or image files) of a module is pretty easy. Just place a file in the same path in your solution and let the Virtual File System to handle it. ## Manipulating the Bundles -The [Bundling & Minification](Bundling-Minification.md) system provides an extensible and dynamic system to create script and style bundles. It allows to extend and manipulate existing bundles by design. +The [Bundling & Minification](Bundling-Minification.md) system provides an **extensible and dynamic** system to create **script** and **style** bundles. It allows you to extend and manipulate the existing bundles. ### Example: Add a Global CSS File -For example, ABP Framework defines a global CSS bundle which is added to every page (actually, added to the layout file by the themes). Let's add a custom CSS file to the end of the bundle files, so we can override any global style. +For example, ABP Framework defines a **global style bundle** which is added to every page (actually, added to the layout by the themes). Let's add a **custom style file** to the end of the bundle files, so we can override any global style. First, create a CSS file and locate it in a folder inside the `wwwroot`: @@ -209,7 +209,7 @@ Just like the `StandardBundles.Styles.Global`, there is a `StandardBundles.Scrip ### Example: Manipulate the Bundle Files -The example above adds a new file to the bundle. You can do more if you create a bundle contributor class. Example: +The example above adds a new file to the bundle. You can do more if you create a **bundle contributor** class. Example: ````csharp public class MyGlobalStyleBundleContributor : BundleContributor @@ -241,9 +241,9 @@ It is not a good idea to clear all CSS files. In a real world scenario, you can ### Example: Add a JavaScript File for a Specific Page -The examples above works with the global bundle added to the layout. What if you want to add a CSS/JavaScript file (or replace a file) for a specific page defines inside a depended module. +The examples above works with the global bundle added to the layout. What if you want to add a CSS/JavaScript file (or replace a file) for a specific page defines inside a depended module? -Assume that you want to run a JavaScript code once user enters to the Role Management page of the Identity Module. +Assume that you want to run a **JavaScript code** once the user enters to the **Role Management** page of the Identity Module. First, create a standard JavaScript file under the `wwwroot`, `Pages` or `Views` folder (ABP support to add static resources inside these folders by default). We prefer the `Pages/Identity/Roles` folder to follow the conventions: @@ -276,40 +276,38 @@ Configure(options => > Notice that not every page defines such page bundles. They define only if needed. -In addition to adding new CSS/JavaScript file to a page, you know you also can replace the existing one. +In addition to adding new CSS/JavaScript file to a page, you also can replace the existing one (by defining a bundle contributor). ## Layout Customization -Layouts are defined by the theme ([see the theming](Theming.md)) by design. They are not included in a downloaded application solution. In this way you can easily upgrade the theme and get new features. +Layouts are defined by the theme ([see the theming](Theming.md)) by design. They are not included in a downloaded application solution. In this way you can easily **upgrade** the theme and get new features. You can not **directly change** the layout code in your application unless you replace it by your own layout (will be explained in the next sections). -However, there are some common ways to customize the layout described in the next sections. +There are some common ways to **customize the layout** described in the next sections. ### Menu Contributors -There are two standard menus defined by the ABP Framework: +There are two **standard menus** defined by the ABP Framework: ![bookstore-menus-highlighted](../../images/bookstore-menus-highlighted.png) * `StandardMenus.Main`: The main menu of the application. * `StandardMenus.User`: The user menu (generally at the top right of the screen). -Rendering the menus is a responsibility of the theme, but menu items are determined by the modules and your application code. Just implement the `IMenuContributor` interface and manipulate the menu items in the `ConfigureMenuAsync` method. +Rendering the menus is a responsibility of the theme, but **menu items** are determined by the modules and your application code. Just implement the `IMenuContributor` interface and **manipulate the menu items** in the `ConfigureMenuAsync` method. -Menu contributors are executed whenever need to render the menu. There is already a menu contributor defined in the application startup template, so you can take it as an example and improve if necessary. See the [navigation menu](Navigation-Menu.md) document for more. +Menu contributors are executed whenever need to render the menu. There is already a menu contributor defined in the **application startup template**, so you can take it as an example and improve if necessary. See the [navigation menu](Navigation-Menu.md) document for more. ### Toolbar Contributors -[Toolbar system](Toolbars.md) is used to define toolbars on the user interface. Modules (or your application) can add items to a toolbar, then the theme renders the toolbar on the layout. +[Toolbar system](Toolbars.md) is used to define **toolbars** on the user interface. Modules (or your application) can add **items** to a toolbar, then the theme renders the toolbar on the **layout**. -There is only one standard toolbar (named "Main" - defined as a constant: `StandardToolbars.Main`). For the basic theme, it is rendered as shown below:![bookstore-toolbar-highlighted](../../images/bookstore-toolbar-highlighted.png) +There is only one **standard toolbar** (named "Main" - defined as a constant: `StandardToolbars.Main`). For the basic theme, it is rendered as shown below:![bookstore-toolbar-highlighted](../../images/bookstore-toolbar-highlighted.png) In the screenshot above, there are two items added to the main toolbar: Language switch component & user menu. You can add your own items here. #### Example: Add a Notification Icon -In this example, we will add a notification (bell) icon to the left of the language switch item. - -A item in the toolbar should be a **view component**. So, first, create a new view component in your project: +In this example, we will add a **notification (bell) icon** to the left of the language switch item. A item in the toolbar should be a **view component**. So, first, create a new view component in your project: ![bookstore-notification-view-component](../../images/bookstore-notification-view-component.png) @@ -366,26 +364,17 @@ That's all, you will see the notification icon on the toolbar when you run the a ![bookstore-notification-icon-on-toolbar](../../images/bookstore-notification-icon-on-toolbar.png) -`NotificationViewComponent` in this sample simply returns a view without any data. In real life, you probably want to query database (or an HTTP API) to get notifications and pass to the view. If you need, you can add a `JavaScript` or `CSS` file to the global bundle (as described before) for your toolbar item. +`NotificationViewComponent` in this sample simply returns a view without any data. In real life, you probably want to **query database** (or call an HTTP API) to get notifications and pass to the view. If you need, you can add a `JavaScript` or `CSS` file to the global bundle (as described before) for your toolbar item. See the [toolbars document](Toolbars.md) for more about the toolbar system. ### Layout Hooks -[Layout Hooks](Layout-Hooks.md) system allows you to add code at some specific parts of the layout. Given standard hook names are defined by the ABP framework: - -* **"Header.First"** (Defined as a constant: `LayoutHooks.Head.First`): To add code to the beginning in the `head` HTML element. -* **"Header.Last"** (Defined as a constant: `LayoutHooks.Head.Last`): To add code to the end in the `head` HTML element. -* **"Body.First"** (Defined as a constant: `LayoutHooks.Body.First`): To add code to the beginning in the `head` HTML element. -* **"Body.Last"** (Defined as a constant: `LayoutHooks.Body.Last`): To add code to the end in the `head` HTML element. - -All layouts of all themes should implement these hooks. You can then add a view component into any of the hook points. +[Layout Hooks](Layout-Hooks.md) system allows you to **add code** at some specific parts of the layout. All layouts of all themes should implement these hooks. Then you can then add a **view component** into a hook point. #### Example: Add Google Analytics Script -Assume that you need to add the Google Analytics script to the layout (that will be available for all the pages). - -First, create a view component in your project: +Assume that you need to add the Google Analytics script to the layout (that will be available for all the pages). First, **create a view component** in your project: ![bookstore-google-analytics-view-component](../../images/bookstore-google-analytics-view-component.png) @@ -439,7 +428,7 @@ Configure(options => options.Add( LayoutHooks.Head.Last, typeof(GoogleAnalyticsViewComponent), - layout: StandardLayouts.Application //The layout to add + layout: StandardLayouts.Application //Set the layout to add ); }); ````