mirror of https://github.com/abpframework/abp.git
64 changed files with 8513 additions and 0 deletions
@ -0,0 +1,74 @@ |
|||
# ASP.NET Core MVC / Razor Pages: Auto-Complete Select |
|||
Um componente de seleção simples às vezes não é útil com uma grande quantidade de dados. O ABP fornece uma implementação de seleção que funciona com paginação e pesquisa no lado do servidor usando o [Select2](https://select2.org/). Ele funciona bem com escolhas únicas ou múltiplas. |
|||
|
|||
Uma captura de tela pode ser mostrada abaixo. |
|||
|
|||
| Único | Múltiplo | |
|||
| --- | --- | |
|||
|  | | |
|||
|
|||
## Começando |
|||
|
|||
Esta é uma funcionalidade central e é usada pelo ABP Framework. Não há instalação personalizada ou pacotes adicionais necessários. |
|||
|
|||
## Uso |
|||
|
|||
Um uso simples é apresentado abaixo. |
|||
|
|||
```html |
|||
<select asp-for="Book.AuthorId" |
|||
class="auto-complete-select" |
|||
data-autocomplete-api-url="/api/app/author" |
|||
data-autocomplete-display-property="name" |
|||
data-autocomplete-value-property="id" |
|||
data-autocomplete-items-property="items" |
|||
data-autocomplete-filter-param-name="filter" |
|||
data-autocomplete-allow-clear="true"> |
|||
|
|||
<!-- Você pode definir a(s) opção(ões) selecionada(s) aqui --> |
|||
<option selected value="@SelectedAuthor.Id">@SelectedAuthor.Name</option> |
|||
</select> |
|||
``` |
|||
|
|||
O select deve ter a classe `auto-complete-select` e os seguintes atributos: |
|||
|
|||
- `data-autocomplete-api-url`: * URL do endpoint da API para obter os itens da seleção. Será enviado uma requisição **GET** para esta URL. |
|||
- `data-autocomplete-display-property`: * Nome da propriedade para exibição. _(Por exemplo: `name` ou `title`. Nome da propriedade da entidade/dto.)_. |
|||
- `data-autocomplete-value-property`: * Nome da propriedade identificadora. _(Por exemplo: `id`)_. |
|||
- `data-autocomplete-items-property`: * Nome da propriedade da coleção no objeto de resposta. _(Por exemplo: `items`)_ |
|||
- `data-autocomplete-filter-param-name`: * Nome da propriedade de texto de filtro. _(Por exemplo: `filter`)_. |
|||
- `data-autocomplete-selected-item-name`: Texto para exibir como item selecionado. |
|||
- `data-autocomplete-parent-selector`: Expressão seletora jQuery para o DOM pai. _(Se estiver em um modal, é sugerido enviar o seletor do modal como este parâmetro)_. |
|||
- `data-autocomplete-allow-clear`: Se `true`, permitirá limpar o valor selecionado. Valor padrão: `false`. |
|||
- `data-autocomplete-placeholder`: Texto de espaço reservado para exibir quando nenhum valor estiver selecionado. |
|||
|
|||
Além disso, o(s) valor(es) selecionado(s) deve(m) ser definido(s) com as tags `<option>` dentro do select, uma vez que a paginação é aplicada e as opções selecionadas podem não ter sido carregadas ainda. |
|||
|
|||
|
|||
### Escolhas Múltiplas |
|||
O AutoComplete Select suporta escolhas múltiplas. Se a tag select tiver o atributo `multiple`, permitirá escolher várias opções. |
|||
|
|||
```html |
|||
<select asp-for="Book.TagIds" |
|||
class="auto-complete-select" |
|||
multiple="multiple" |
|||
data-autocomplete-api-url="/api/app/tags" |
|||
data-autocomplete-display-property="name" |
|||
data-autocomplete-value-property="id" |
|||
data-autocomplete-items-property="items" |
|||
data-autocomplete-filter-param-name="filter"> |
|||
@foreach(var tag in SelectedTags) |
|||
{ |
|||
<option selected value="@tag.Id">@tag.Name</option> |
|||
} |
|||
</select> |
|||
``` |
|||
|
|||
Será automaticamente vinculado a uma coleção do tipo de valor definido. |
|||
```csharp |
|||
public List<Guid> TagIds { get; set; } |
|||
``` |
|||
|
|||
## Avisos |
|||
Se o usuário autenticado não tiver permissão na URL fornecida, o usuário receberá um erro de autorização. Tenha cuidado ao projetar esse tipo de interface de usuário. |
|||
Você pode criar um endpoint/método específico, [não autorizado](../../Authorization.md), para obter a lista de itens, para que a página possa recuperar dados de pesquisa de uma entidade dependente sem dar permissão de leitura completa aos usuários. |
|||
@ -0,0 +1,96 @@ |
|||
# ASP.NET Core MVC / Razor Pages: O Tema Básico |
|||
|
|||
O Tema Básico é uma implementação de tema para a interface do usuário do ASP.NET Core MVC / Razor Pages. É um tema minimalista que não adiciona nenhum estilo além do [Bootstrap](https://getbootstrap.com/) básico. Você pode usar o Tema Básico como o **tema base** e construir seu próprio tema ou estilo em cima dele. Veja a seção *Customização*. |
|||
|
|||
O Tema Básico possui suporte para idiomas da direita para a esquerda (RTL). |
|||
|
|||
> Se você está procurando um tema profissional e pronto para uso empresarial, você pode conferir o [Tema Lepton](https://commercial.abp.io/themes), que faz parte do [ABP Commercial](https://commercial.abp.io/). |
|||
|
|||
> Veja o documento [Theming](Theming.md) para aprender sobre temas. |
|||
|
|||
## Instalação |
|||
|
|||
Se você precisa instalar manualmente este tema, siga os passos abaixo: |
|||
|
|||
* Instale o pacote NuGet [Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic) em seu projeto web. |
|||
* Adicione `AbpAspNetCoreMvcUiBasicThemeModule` no atributo `[DependsOn(...)]` para a sua [classe de módulo](../../Module-Development-Basics.md) no projeto web. |
|||
* Instale o pacote NPM [@abp/aspnetcore.mvc.ui.theme.basic](https://www.npmjs.com/package/@abp/aspnetcore.mvc.ui.theme.basic) em seu projeto web (por exemplo, `npm install @abp/aspnetcore.mvc.ui.theme.basic` ou `yarn add @abp/aspnetcore.mvc.ui.theme.basic`). |
|||
* Execute o comando `abp install-libs` em um terminal de linha de comando na pasta do projeto web. |
|||
|
|||
## Layouts |
|||
|
|||
O Tema Básico implementa os layouts padrão. Todos os layouts implementam as seguintes partes: |
|||
|
|||
* [Bundles](Bundling-Minification.md) globais |
|||
* [Alertas de página](Page-Alerts.md) |
|||
* [Hooks de layout](Layout-Hooks.md) |
|||
* Recursos de [widget](Widgets.md) |
|||
|
|||
### O Layout da Aplicação |
|||
|
|||
 |
|||
|
|||
O Layout da Aplicação implementa as seguintes partes, além das partes comuns mencionadas acima: |
|||
|
|||
* Marca |
|||
* [Menu](Navigation-Menu.md) principal |
|||
* [Toolbar](Toolbars.md) principal com seleção de idioma e menu do usuário |
|||
|
|||
### O Layout da Conta |
|||
|
|||
 |
|||
|
|||
O Layout da Conta implementa as seguintes partes, além das partes comuns mencionadas acima: |
|||
|
|||
* Marca |
|||
* [Menu](Navigation-Menu.md) principal |
|||
* [Toolbar](Toolbars.md) principal com seleção de idioma e menu do usuário |
|||
* Área de troca de inquilino |
|||
|
|||
### Layout Vazio |
|||
|
|||
O layout vazio é vazio, como o nome sugere. No entanto, ele implementa as partes comuns mencionadas acima. |
|||
|
|||
## Customização |
|||
|
|||
Você tem duas opções para personalizar este tema: |
|||
|
|||
### Sobrescrevendo Estilos/Componentes |
|||
|
|||
Nesta abordagem, você continua a usar o tema como pacotes NuGet e NPM e personaliza as partes que precisa. Existem várias maneiras de personalizá-lo; |
|||
|
|||
#### Sobrescrever os Estilos |
|||
|
|||
1. Crie um arquivo CSS na pasta `wwwroot` do seu projeto: |
|||
|
|||
 |
|||
|
|||
2. Adicione o arquivo de estilo ao bundle global, no método `ConfigureServices` da sua [classe de módulo](../../Module-Development-Basics.md): |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.StyleBundles.Configure(BasicThemeBundles.Styles.Global, bundle => |
|||
{ |
|||
bundle.AddFiles("/styles/global-styles.css"); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
#### Sobrescrever os Componentes |
|||
|
|||
Veja o [Guia de Customização da Interface do Usuário](Customization-User-Interface.md) para aprender como substituir componentes, personalizar e estender a interface do usuário. |
|||
|
|||
### Copiar e Personalizar |
|||
|
|||
Você pode executar o seguinte comando [ABP CLI](../../CLI.md) no diretório do projeto **Web** para copiar o código-fonte para a sua solução: |
|||
|
|||
`abp add-module Volo.BasicTheme --with-source-code --add-to-solution-file` |
|||
|
|||
---- |
|||
|
|||
Ou, você pode baixar o [código-fonte](https://github.com/abpframework/abp/tree/dev/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic) do Tema Básico, copiar manualmente o conteúdo do projeto para a sua solução, reorganizar as dependências de pacote/módulo (veja a seção de Instalação acima para entender como ele foi instalado no projeto) e personalizar livremente o tema com base nos requisitos da sua aplicação. |
|||
|
|||
## Veja também |
|||
|
|||
* [Theming](Theming.md) |
|||
@ -0,0 +1,45 @@ |
|||
# ASP.NET Core MVC / Razor Pages: Branding |
|||
|
|||
## IBrandingProvider |
|||
|
|||
`IBrandingProvider` é uma interface simples que é usada para mostrar o nome e o logotipo da aplicação no layout. |
|||
|
|||
A captura de tela abaixo mostra *MyProject* como o nome da aplicação: |
|||
|
|||
 |
|||
|
|||
Você pode implementar a interface `IBrandingProvider` ou herdar da classe `DefaultBrandingProvider` para definir o nome da aplicação: |
|||
|
|||
````csharp |
|||
using Volo.Abp.Ui.Branding; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace MyProject.Web |
|||
{ |
|||
[Dependency(ReplaceServices = true)] |
|||
public class MyProjectBrandingProvider : DefaultBrandingProvider |
|||
{ |
|||
public override string AppName => "Book Store"; |
|||
|
|||
public override string LogoUrl => "/logo.png"; |
|||
} |
|||
} |
|||
```` |
|||
|
|||
> Atualmente, definir o `AppName` só é aplicável ao [Tema Básico](../../Themes/Basic.md), não tem efeito nos outros [temas oficiais](../../Themes/Index.md). |
|||
|
|||
O resultado será como mostrado abaixo: |
|||
|
|||
 |
|||
|
|||
`IBrandingProvider` possui as seguintes propriedades: |
|||
|
|||
* `AppName`: O nome da aplicação. |
|||
* `LogoUrl`: Uma URL para mostrar o logotipo da aplicação. |
|||
* `LogoReverseUrl`: Uma URL para mostrar o logotipo da aplicação em um tema de cor reversa (escuro, por exemplo). |
|||
|
|||
> **Dica**: `IBrandingProvider` é usado em cada atualização de página. Para uma aplicação multi-inquilino, você pode retornar um nome de aplicação específico do inquilino para personalizá-lo por inquilino. |
|||
|
|||
## Sobrescrevendo a Área de Branding |
|||
|
|||
Você pode consultar o [Guia de Customização de UI](Customization-User-Interface.md) para aprender como substituir a área de branding por um componente de visualização personalizado. |
|||
@ -0,0 +1,479 @@ |
|||
# ASP.NET Core MVC Bundling & Minification |
|||
|
|||
Existem várias maneiras de agrupar e minificar recursos do lado do cliente (arquivos JavaScript e CSS). As formas mais comuns são: |
|||
|
|||
* Usando a extensão do Visual Studio [Bundler & Minifier](https://marketplace.visualstudio.com/items?itemName=MadsKristensen.BundlerMinifier) ou o [pacote NuGet](https://www.nuget.org/packages/BuildBundlerMinifier/). |
|||
* Usando os gerenciadores de tarefas [Gulp](https://gulpjs.com/)/[Grunt](https://gruntjs.com/) e seus plugins. |
|||
|
|||
O ABP oferece uma maneira simples, dinâmica, poderosa, modular e integrada. |
|||
|
|||
## Pacote Volo.Abp.AspNetCore.Mvc.UI.Bundling |
|||
|
|||
> Este pacote já está instalado por padrão nos modelos de inicialização. Portanto, na maioria das vezes, você não precisa instalá-lo manualmente. |
|||
|
|||
Se você não estiver usando um modelo de inicialização, pode usar o [ABP CLI](../../CLI.md) para instalá-lo em seu projeto. Execute o seguinte comando na pasta que contém o arquivo .csproj do seu projeto: |
|||
|
|||
```` |
|||
abp add-package Volo.Abp.AspNetCore.Mvc.UI.Bundling |
|||
```` |
|||
|
|||
> Se você ainda não o fez, primeiro precisa instalar o [ABP CLI](../../CLI.md). Para outras opções de instalação, consulte [a página de descrição do pacote](https://abp.io/package-detail/Volo.Abp.AspNetCore.Mvc.UI.Bundling). |
|||
|
|||
## Tag Helpers de Agrupamento Razor |
|||
|
|||
A maneira mais simples de criar um pacote é usar os tag helpers `abp-script-bundle` ou `abp-style-bundle`. Exemplo: |
|||
|
|||
````html |
|||
<abp-style-bundle name="MyGlobalBundle"> |
|||
<abp-style src="/libs/bootstrap/css/bootstrap.css" /> |
|||
<abp-style src="/libs/font-awesome/css/font-awesome.css" /> |
|||
<abp-style src="/libs/toastr/toastr.css" /> |
|||
<abp-style src="/styles/my-global-style.css" /> |
|||
</abp-style-bundle> |
|||
```` |
|||
|
|||
Este pacote define um pacote de estilo com um **nome único**: `MyGlobalBundle`. É muito fácil entender como usá-lo. Vamos ver como ele *funciona*: |
|||
|
|||
* O ABP cria o pacote como **lazy** a partir dos arquivos fornecidos quando é **solicitado pela primeira vez**. Para as chamadas subsequentes, ele é retornado do **cache**. Isso significa que, se você adicionar condicionalmente os arquivos ao pacote, ele será executado apenas uma vez e quaisquer alterações na condição não afetarão o pacote para as próximas solicitações. |
|||
* O ABP adiciona os arquivos do pacote **individualmente** à página para o ambiente `development`. Ele agrupa e minifica automaticamente para outros ambientes (`staging`, `production`...). Consulte a seção *Modo de Agrupamento* para alterar esse comportamento. |
|||
* Os arquivos do pacote podem ser arquivos **físicos** ou [**virtuais/embutidos**](../../Virtual-File-System.md). |
|||
* O ABP adiciona automaticamente uma **string de consulta de versão** ao URL do arquivo do pacote para evitar que os navegadores armazenem em cache quando o pacote está sendo atualizado. (como ?_v=67872834243042 - gerado a partir da última data de alteração dos arquivos relacionados). A versão funciona mesmo se os arquivos do pacote forem adicionados individualmente à página (no ambiente de desenvolvimento). |
|||
|
|||
### Importando os Tag Helpers de Agrupamento |
|||
|
|||
> Isso já é importado por padrão nos modelos de inicialização. Portanto, na maioria das vezes, você não precisa adicioná-lo manualmente. |
|||
|
|||
Para usar os tag helpers de pacote, você precisa adicioná-los ao seu arquivo `_ViewImports.cshtml` ou à sua página: |
|||
|
|||
```` |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling |
|||
```` |
|||
|
|||
### Pacotes sem nome |
|||
|
|||
O nome é **opcional** para os tag helpers de pacote razor. Se você não definir um nome, ele será **calculado** automaticamente com base nos nomes dos arquivos do pacote usados (eles são **concatenados** e **hashados**). Exemplo: |
|||
|
|||
````html |
|||
<abp-style-bundle> |
|||
<abp-style src="/libs/bootstrap/css/bootstrap.css" /> |
|||
<abp-style src="/libs/font-awesome/css/font-awesome.css" /> |
|||
<abp-style src="/libs/toastr/toastr.css" /> |
|||
@if (ViewBag.IncludeCustomStyles != false) |
|||
{ |
|||
<abp-style src="/styles/my-global-style.css" /> |
|||
} |
|||
</abp-style-bundle> |
|||
```` |
|||
|
|||
Isso pode criar **dois pacotes diferentes** (um inclui o `my-global-style.css` e o outro não). |
|||
|
|||
Vantagens de pacotes **sem nome**: |
|||
|
|||
* É possível **adicionar itens condicionalmente** ao pacote. Mas isso pode levar a várias variações do pacote com base nas condições. |
|||
|
|||
Vantagens de pacotes **com nome**: |
|||
|
|||
* Outros **módulos podem contribuir** para o pacote pelo nome (consulte as seções abaixo). |
|||
|
|||
### Arquivo Único |
|||
|
|||
Se você precisa apenas adicionar um único arquivo à página, pode usar a tag `abp-script` ou `abp-style` sem envolvê-la na tag `abp-script-bundle` ou `abp-style-bundle`. Exemplo: |
|||
|
|||
````xml |
|||
<abp-script src="/scripts/my-script.js" /> |
|||
```` |
|||
|
|||
O nome do pacote será *scripts.my-scripts* para o exemplo acima ("/" é substituído por "."). Todos os recursos de agrupamento funcionam como esperado para pacotes de arquivo único também. |
|||
|
|||
## Opções de Agrupamento |
|||
|
|||
Se você precisa usar o mesmo pacote em **múltiplas páginas** ou deseja usar alguns recursos mais **poderosos**, você pode configurar pacotes **por código** em sua classe de [módulo](../../Module-Development-Basics.md). |
|||
|
|||
### Criando um Novo Pacote |
|||
|
|||
Exemplo de uso: |
|||
|
|||
````C# |
|||
[DependsOn(typeof(AbpAspNetCoreMvcUiBundlingModule))] |
|||
public class MyWebModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options |
|||
.ScriptBundles |
|||
.Add("MyGlobalBundle", bundle => { |
|||
bundle.AddFiles( |
|||
"/libs/jquery/jquery.js", |
|||
"/libs/bootstrap/js/bootstrap.js", |
|||
"/libs/toastr/toastr.min.js", |
|||
"/scripts/my-global-scripts.js" |
|||
); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
> Você pode usar o mesmo nome (*MyGlobalBundle* aqui) para um pacote de script e estilo, pois eles são adicionados a coleções diferentes (`ScriptBundles` e `StyleBundles`). |
|||
|
|||
Após definir um pacote desse tipo, ele pode ser incluído em uma página usando os mesmos tag helpers definidos acima. Exemplo: |
|||
|
|||
````html |
|||
<abp-script-bundle name="MyGlobalBundle" /> |
|||
```` |
|||
|
|||
Desta vez, nenhum arquivo é definido na definição do tag helper porque os arquivos do pacote são definidos pelo código. |
|||
|
|||
### Configurando um Pacote Existente |
|||
|
|||
O ABP também oferece suporte à [modularidade](../../Module-Development-Basics.md) para agrupamento. Um módulo pode modificar um pacote existente criado por um módulo dependente. Exemplo: |
|||
|
|||
````C# |
|||
[DependsOn(typeof(MyWebModule))] |
|||
public class MyWebExtensionModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options |
|||
.ScriptBundles |
|||
.Configure("MyGlobalBundle", bundle => { |
|||
bundle.AddFiles( |
|||
"/scripts/my-extension-script.js" |
|||
); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Você também pode usar o método `ConfigureAll` para configurar todos os pacotes existentes: |
|||
|
|||
````C# |
|||
[DependsOn(typeof(MyWebModule))] |
|||
public class MyWebExtensionModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options |
|||
.ScriptBundles |
|||
.ConfigureAll(bundle => { |
|||
bundle.AddFiles( |
|||
"/scripts/my-extension-script.js" |
|||
); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
## Contribuidores de Pacotes |
|||
|
|||
Adicionar arquivos a um pacote existente é útil. E se você precisar **substituir** um arquivo no pacote ou quiser adicionar arquivos **condicionalmente**? Definir um contribuidor de pacote fornece poder extra para esses casos. |
|||
|
|||
Um exemplo de contribuidor de pacote que substitui o bootstrap.css por uma versão personalizada: |
|||
|
|||
````C# |
|||
public class MyExtensionGlobalStyleContributor : BundleContributor |
|||
{ |
|||
public override void ConfigureBundle(BundleConfigurationContext context) |
|||
{ |
|||
context.Files.ReplaceOne( |
|||
"/libs/bootstrap/css/bootstrap.css", |
|||
"/styles/extensions/bootstrap-customized.css" |
|||
); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Em seguida, você pode usar esse contribuidor da seguinte maneira: |
|||
|
|||
````C# |
|||
services.Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options |
|||
.ScriptBundles |
|||
.Configure("MyGlobalBundle", bundle => { |
|||
bundle.AddContributors(typeof(MyExtensionGlobalStyleContributor)); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
> Você também pode adicionar contribuidores ao criar um novo pacote. |
|||
|
|||
Os contribuidores também podem ser usados nos tag helpers de pacote. Exemplo: |
|||
|
|||
````xml |
|||
<abp-style-bundle> |
|||
<abp-style type="@typeof(BootstrapStyleContributor)" /> |
|||
<abp-style src="/libs/font-awesome/css/font-awesome.css" /> |
|||
<abp-style src="/libs/toastr/toastr.css" /> |
|||
</abp-style-bundle> |
|||
```` |
|||
|
|||
As tags `abp-style` e `abp-script` podem receber atributos `type` (em vez de atributos `src`) como mostrado neste exemplo. Quando você adiciona um contribuidor de pacote, suas dependências também são adicionadas automaticamente ao pacote. |
|||
|
|||
### Dependências de Contribuidores |
|||
|
|||
Um contribuidor de pacote pode ter uma ou mais dependências de outros contribuidores. |
|||
Exemplo: |
|||
|
|||
````C# |
|||
[DependsOn(typeof(MyDependedBundleContributor))] //Define a dependência |
|||
public class MyExtensionStyleBundleContributor : BundleContributor |
|||
{ |
|||
//... |
|||
} |
|||
```` |
|||
|
|||
Quando um contribuidor de pacote é adicionado, suas dependências são adicionadas **automaticamente e recursivamente**. As dependências são adicionadas pela **ordem de dependência** evitando **duplicatas**. As duplicatas são evitadas mesmo que estejam em pacotes separados. O ABP organiza todos os pacotes em uma página e elimina duplicações. |
|||
|
|||
Criar contribuidores e definir dependências é uma maneira de organizar a criação de pacotes em diferentes módulos. |
|||
|
|||
### Extensões de Contribuidores |
|||
|
|||
Em alguns cenários avançados, você pode querer fazer alguma configuração adicional sempre que um contribuidor de pacote for usado. As extensões de contribuidor funcionam perfeitamente quando o contribuidor estendido é usado. |
|||
|
|||
O exemplo abaixo adiciona alguns estilos para a biblioteca prism.js: |
|||
|
|||
````csharp |
|||
public class MyPrismjsStyleExtension : BundleContributor |
|||
{ |
|||
public override void ConfigureBundle(BundleConfigurationContext context) |
|||
{ |
|||
context.Files.AddIfNotContains("/libs/prismjs/plugins/toolbar/prism-toolbar.css"); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Em seguida, você pode configurar `AbpBundleContributorOptions` para estender o `PrismjsStyleBundleContributor` existente. |
|||
|
|||
````csharp |
|||
Configure<AbpBundleContributorOptions>(options => |
|||
{ |
|||
options |
|||
.Extensions<PrismjsStyleBundleContributor>() |
|||
.Add<MyPrismjsStyleExtension>(); |
|||
}); |
|||
```` |
|||
|
|||
Sempre que `PrismjsStyleBundleContributor` for adicionado a um pacote, `MyPrismjsStyleExtension` também será adicionado automaticamente. |
|||
|
|||
### Acessando o IServiceProvider |
|||
|
|||
Embora raramente seja necessário, `BundleConfigurationContext` possui uma propriedade `ServiceProvider` que permite resolver dependências de serviço dentro do método `ConfigureBundle`. |
|||
|
|||
### Contribuidores de Pacotes Padrão |
|||
|
|||
Adicionar um recurso específico do pacote NPM (arquivos js, css) a um pacote é bastante simples para esse pacote. Por exemplo, você sempre adiciona o arquivo `bootstrap.css` para o pacote NPM do bootstrap. |
|||
|
|||
Existem contribuidores embutidos para todos os [pacotes NPM padrão](Client-Side-Package-Management.md). Por exemplo, se seu contribuidor depende do bootstrap, você pode apenas declará-lo, em vez de adicionar o bootstrap.css você mesmo. |
|||
|
|||
````C# |
|||
[DependsOn(typeof(BootstrapStyleContributor))] //Define a dependência de estilo do bootstrap |
|||
public class MyExtensionStyleBundleContributor : BundleContributor |
|||
{ |
|||
//... |
|||
} |
|||
```` |
|||
|
|||
Usando os contribuidores embutidos para pacotes padrão; |
|||
|
|||
* Impede que você digite **os caminhos de recursos inválidos**. |
|||
* Impede a alteração do seu contribuidor se o **caminho do recurso mudar** (o contribuidor dependente lidará com isso). |
|||
* Impede que vários módulos adicionem **arquivos duplicados**. |
|||
* Gerencia **dependências recursivamente** (adiciona dependências de dependências, se necessário). |
|||
|
|||
#### Pacote Volo.Abp.AspNetCore.Mvc.UI.Packages |
|||
|
|||
> Este pacote já está instalado por padrão nos modelos de inicialização. Portanto, na maioria das vezes, você não precisa instalá-lo manualmente. |
|||
|
|||
Se você não estiver usando um modelo de inicialização, pode usar o [ABP CLI](../../CLI.md) para instalá-lo em seu projeto. Execute o seguinte comando na pasta que contém o arquivo .csproj do seu projeto: |
|||
|
|||
```` |
|||
abp add-package Volo.Abp.AspNetCore.Mvc.UI.Packages |
|||
```` |
|||
|
|||
> Se você ainda não o fez, primeiro precisa instalar o [ABP CLI](../../CLI.md). Para outras opções de instalação, consulte [a página de descrição do pacote](https://abp.io/package-detail/Volo.Abp.AspNetCore.Mvc.UI.Packages). |
|||
|
|||
### Herança de Pacotes |
|||
|
|||
Em alguns casos específicos, pode ser necessário criar um **novo** pacote **herdado** de outro(s) pacote(s). Ao herdar de um pacote (recursivamente), todos os arquivos/contribuidores desse pacote são herdados. Em seguida, o pacote derivado pode adicionar ou modificar arquivos/contribuidores **sem modificar** o pacote original. |
|||
Exemplo: |
|||
|
|||
````c# |
|||
services.Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options |
|||
.StyleBundles |
|||
.Add("MyTheme.MyGlobalBundle", bundle => { |
|||
bundle |
|||
.AddBaseBundles("MyGlobalBundle") //Pode adicionar vários |
|||
.AddFiles( |
|||
"/styles/mytheme-global-styles.css" |
|||
); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
## Opções Adicionais |
|||
|
|||
Esta seção mostra outras opções úteis para o sistema de agrupamento e minificação. |
|||
|
|||
### Modo de Agrupamento |
|||
|
|||
O ABP adiciona arquivos de pacote individualmente à página para o ambiente `development`. Ele agrupa e minifica automaticamente para outros ambientes (`staging`, `production`...). Na maioria das vezes, esse é o comportamento desejado. No entanto, você pode configurá-lo manualmente em alguns casos. Existem quatro modos; |
|||
|
|||
* `Auto`: Determina automaticamente o modo com base no ambiente. |
|||
* `None`: Sem agrupamento ou minificação. |
|||
* `Bundle`: Agrupado, mas não minificado. |
|||
* `BundleAndMinify`: Agrupado e minificado. |
|||
|
|||
Você pode configurar `AbpBundlingOptions` no `ConfigureServices` do seu [módulo](../../Module-Development-Basics.md). |
|||
|
|||
**Exemplo:** |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.Mode = BundlingMode.Bundle; |
|||
}); |
|||
```` |
|||
|
|||
### Ignorar para Minificação |
|||
|
|||
É possível ignorar um arquivo específico para a minificação. |
|||
|
|||
**Exemplo:** |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.MinificationIgnoredFiles.Add("/scripts/myscript.js"); |
|||
}); |
|||
```` |
|||
|
|||
O arquivo fornecido ainda é adicionado ao pacote, mas não é minificado neste caso. |
|||
|
|||
### Carregar JavaScript e CSS de forma assíncrona |
|||
|
|||
Você pode configurar `AbpBundlingOptions` para carregar todos ou um único arquivo js/css de forma assíncrona. |
|||
|
|||
**Exemplo:** |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.PreloadStyles.Add("/__bundles/Basic.Global"); |
|||
options.DeferScriptsByDefault = true; |
|||
}); |
|||
```` |
|||
|
|||
**HTML de saída:** |
|||
````html |
|||
<link rel="preload" href="/__bundles/Basic.Global.F4FA61F368098407A4C972D0A6914137.css?_v=637697363694828051" as="style" onload="this.rel='stylesheet'"/> |
|||
|
|||
<script defer src="/libs/timeago/locales/jquery.timeago.en.js?_v=637674729040000000"></script> |
|||
```` |
|||
|
|||
### Suporte a Arquivos Externos/CDN |
|||
|
|||
O sistema de agrupamento reconhece automaticamente os arquivos externos/CDN e os adiciona à página sem nenhuma alteração. |
|||
|
|||
#### Usando Arquivos Externos/CDN em `AbpBundlingOptions` |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.StyleBundles |
|||
.Add("MyStyleBundle", configuration => |
|||
{ |
|||
configuration |
|||
.AddFiles("/styles/my-style1.css") |
|||
.AddFiles("/styles/my-style2.css") |
|||
.AddFiles("https://cdn.abp.io/bootstrap.css") |
|||
.AddFiles("/styles/my-style3.css") |
|||
.AddFiles("/styles/my-style4.css"); |
|||
}); |
|||
|
|||
options.ScriptBundles |
|||
.Add("MyScriptBundle", configuration => |
|||
{ |
|||
configuration |
|||
.AddFiles("/scripts/my-script1.js") |
|||
.AddFiles("/scripts/my-script2.js") |
|||
.AddFiles("https://cdn.abp.io/bootstrap.js") |
|||
.AddFiles("/scripts/my-script3.js") |
|||
.AddFiles("/scripts/my-script4.js"); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
**HTML de saída:** |
|||
|
|||
````html |
|||
<link rel="stylesheet" href="/__bundles/MyStyleBundle.EA8C28419DCA43363E9670973D4C0D15.css?_v=638331889644609730" /> |
|||
<link rel="stylesheet" href="https://cdn.abp.io/bootstrap.css" /> |
|||
<link rel="stylesheet" href="/__bundles/MyStyleBundle.AC2E0AA6C461A0949A1295E9BDAC049C.css?_v=638331889644623860" /> |
|||
|
|||
<script src="/__bundles/MyScriptBundle.C993366DF8840E08228F3EE685CB08E8.js?_v=638331889644937120"></script> |
|||
<script src="https://cdn.abp.io/bootstrap.js"></script> |
|||
<script src="/__bundles/MyScriptBundle.2E8D0FDC6334D2A6B847393A801525B7.js?_v=638331889644943970"></script> |
|||
```` |
|||
|
|||
#### Usando Arquivos Externos/CDN em Tag Helpers. |
|||
|
|||
````html |
|||
<abp-style-bundle name="MyStyleBundle"> |
|||
<abp-style src="/styles/my-style1.css" /> |
|||
<abp-style src="/styles/my-style2.css" /> |
|||
<abp-style src="https://cdn.abp.io/bootstrap.css" /> |
|||
<abp-style src="/styles/my-style3.css" /> |
|||
<abp-style src="/styles/my-style4.css" /> |
|||
</abp-style-bundle> |
|||
|
|||
<abp-script-bundle name="MyScriptBundle"> |
|||
<abp-script src="/scripts/my-script1.js" /> |
|||
<abp-script src="/scripts/my-script2.js" /> |
|||
<abp-script src="https://cdn.abp.io/bootstrap.js" /> |
|||
<abp-script src="/scripts/my-script3.js" /> |
|||
<abp-script src="/scripts/my-script4.js" /> |
|||
</abp-script-bundle> |
|||
```` |
|||
|
|||
**HTML de saída:** |
|||
|
|||
````html |
|||
<link rel="stylesheet" href="/__bundles/MyStyleBundle.C60C7B9C1F539659623BB6E7227A7C45.css?_v=638331889645002500" /> |
|||
<link rel="stylesheet" href="https://cdn.abp.io/bootstrap.css" /> |
|||
<link rel="stylesheet" href="/__bundles/MyStyleBundle.464328A06039091534650B0E049904C6.css?_v=638331889645012300" /> |
|||
|
|||
<script src="/__bundles/MyScriptBundle.55FDCBF2DCB9E0767AE6FA7487594106.js?_v=638331889645050410"></script> |
|||
<script src="https://cdn.abp.io/bootstrap.js"></script> |
|||
<script src="/__bundles/MyScriptBundle.191CB68AB4F41C8BF3A7AE422F19A3D2.js?_v=638331889645055490"></script> |
|||
```` |
|||
|
|||
## Temas |
|||
|
|||
Os temas usam os contribuidores de pacotes padrão para adicionar recursos de biblioteca aos layouts de página. Os temas também podem definir alguns pacotes padrão/globais, para que qualquer módulo possa contribuir para esses pacotes padrão/globais. Consulte a documentação de [temas](Theming.md) para mais informações. |
|||
|
|||
## Melhores Práticas e Sugestões |
|||
|
|||
É sugerido definir vários pacotes para uma aplicação, cada um usado para diferentes propósitos. |
|||
|
|||
* **Pacote global**: Pacotes de estilo/script globais são incluídos em todas as páginas da aplicação. Os temas já definem pacotes de estilo e script globais. Seu módulo pode contribuir para eles. |
|||
* **Pacotes de layout**: Este é um pacote específico para um layout individual. Contém apenas recursos compartilhados entre todas as páginas que usam o layout. Use os tag helpers de agrupamento para criar o pacote como uma boa prática. |
|||
* **Pacotes de módulo**: Para recursos compartilhados entre as páginas de um módulo individual. |
|||
* **Pacotes de página**: Pacotes específicos criados para cada página. Use os tag helpers de agrupamento para criar o pacote como uma melhor prática. |
|||
|
|||
Estabeleça um equilíbrio entre desempenho, uso de largura de banda da rede e quantidade de pacotes. |
|||
|
|||
## Veja também |
|||
|
|||
* [Gerenciamento de Pacotes do Lado do Cliente](Client-Side-Package-Management.md) |
|||
* [Temas](Theming.md) |
|||
@ -0,0 +1,115 @@ |
|||
## Gerenciamento de Pacotes do Lado do Cliente no ASP.NET Core MVC |
|||
|
|||
O framework ABP pode funcionar com qualquer tipo de sistema de gerenciamento de pacotes do lado do cliente. Você até pode decidir não usar nenhum sistema de gerenciamento de pacotes e gerenciar suas dependências manualmente. |
|||
|
|||
No entanto, o framework ABP funciona melhor com o **NPM/Yarn**. Por padrão, os módulos integrados são configurados para funcionar com o NPM/Yarn. |
|||
|
|||
Por fim, sugerimos o [**Yarn**](https://classic.yarnpkg.com/) em vez do NPM, pois ele é mais rápido, estável e também compatível com o NPM. |
|||
|
|||
### Pacotes NPM do ABP |
|||
|
|||
O ABP é uma plataforma modular. Todo desenvolvedor pode criar módulos e os módulos devem funcionar juntos em um estado **compatível** e **estável**. |
|||
|
|||
Um desafio são as **versões dos pacotes NPM dependentes**. E se dois módulos diferentes usarem a mesma biblioteca JavaScript, mas em versões diferentes (e potencialmente incompatíveis)? |
|||
|
|||
Para resolver o problema de versionamento, criamos um **conjunto padrão de pacotes** que dependem de algumas bibliotecas de terceiros comuns. Alguns exemplos de pacotes são [@abp/jquery](https://www.npmjs.com/package/@abp/jquery), [@abp/bootstrap](https://www.npmjs.com/package/@abp/bootstrap) e [@abp/font-awesome](https://www.npmjs.com/package/@abp/font-awesome). Você pode ver a **lista de pacotes** no [repositório do GitHub](https://github.com/volosoft/abp/tree/master/npm/packs). |
|||
|
|||
A vantagem de um **pacote padrão** é: |
|||
|
|||
* Ele depende de uma **versão padrão** de um pacote. Depender desse pacote é **seguro** porque todos os módulos dependem da mesma versão. |
|||
* Ele contém os mapeamentos para copiar os recursos da biblioteca (arquivos js, css, img...) da pasta `node_modules` para a pasta `wwwroot/libs`. Consulte a seção *Mapeando os Recursos da Biblioteca* para mais informações. |
|||
|
|||
Depender de um pacote padrão é fácil. Basta adicioná-lo ao seu arquivo **package.json** como você normalmente faria. Exemplo: |
|||
|
|||
```json |
|||
{ |
|||
... |
|||
"dependencies": { |
|||
"@abp/bootstrap": "^1.0.0" |
|||
} |
|||
} |
|||
``` |
|||
|
|||
É sugerido depender de um pacote padrão em vez de depender diretamente de um pacote de terceiros. |
|||
|
|||
#### Instalação do Pacote |
|||
|
|||
Depois de depender de um pacote NPM, tudo o que você precisa fazer é executar o comando **yarn** no terminal para instalar todos os pacotes e suas dependências: |
|||
|
|||
```bash |
|||
yarn |
|||
``` |
|||
|
|||
Alternativamente, você pode usar `npm install`, mas o [Yarn](https://classic.yarnpkg.com/) é sugerido como mencionado anteriormente. |
|||
|
|||
#### Contribuição de Pacotes |
|||
|
|||
Se você precisar de um pacote NPM de terceiros que não esteja no conjunto padrão de pacotes, você pode criar uma Pull Request no repositório do Github [repositório](https://github.com/volosoft/abp). Uma Pull Request que segue essas regras é aceita: |
|||
|
|||
* O nome do pacote deve ser `@abp/nome-do-pacote` para um `nome-do-pacote` no NPM (exemplo: `@abp/bootstrap` para o pacote `bootstrap`). |
|||
* Deve ser a versão **mais recente estável** do pacote. |
|||
* Deve depender apenas de um pacote de terceiros. Pode depender de vários pacotes `@abp/*`. |
|||
* O pacote deve incluir um arquivo `abp.resourcemapping.js` formatado como definido na seção *Mapeando os Recursos da Biblioteca*. Este arquivo deve mapear apenas os recursos do pacote dependente. |
|||
* Você também precisa criar [contribuidor(es) de pacote](Bundling-Minification.md) para o pacote que você criou. |
|||
|
|||
Veja os pacotes padrão atuais para exemplos. |
|||
|
|||
### Mapeando os Recursos da Biblioteca |
|||
|
|||
O uso de pacotes NPM e da ferramenta NPM/Yarn é o padrão de fato para bibliotecas do lado do cliente. A ferramenta NPM/Yarn cria uma pasta **node_modules** na pasta raiz do seu projeto da web. |
|||
|
|||
O próximo desafio é copiar os recursos necessários (arquivos js, css, img...) da pasta `node_modules` para uma pasta dentro da pasta **wwwroot** para torná-los acessíveis aos clientes/navegadores. |
|||
|
|||
O comando `abp install-libs` da CLI do ABP **copia os recursos** da pasta **node_modules** para a pasta **wwwroot/libs**. Cada **pacote padrão** (consulte a seção *@ABP NPM Packages*) define o mapeamento para seus próprios arquivos. Portanto, na maioria das vezes, você só precisa configurar as dependências. |
|||
|
|||
Os modelos de inicialização já estão configurados para funcionar com tudo isso. Esta seção explicará as opções de configuração. |
|||
|
|||
#### Arquivo de Definição de Mapeamento de Recursos |
|||
|
|||
Um módulo deve definir um arquivo JavaScript chamado `abp.resourcemapping.js` formatado como no exemplo abaixo: |
|||
|
|||
```json |
|||
module.exports = { |
|||
aliases: { |
|||
"@node_modules": "./node_modules", |
|||
"@libs": "./wwwroot/libs" |
|||
}, |
|||
clean: [ |
|||
"@libs", |
|||
"!@libs/**/foo.txt" |
|||
], |
|||
mappings: { |
|||
|
|||
} |
|||
} |
|||
``` |
|||
|
|||
* A seção **aliases** define aliases padrão (placeholders) que podem ser usados nos caminhos de mapeamento. **@node_modules** e **@libs** são obrigatórios (pelos pacotes padrão), você pode definir seus próprios aliases para reduzir a duplicação. |
|||
* A seção **clean** é uma lista de pastas a serem limpas antes de copiar os arquivos. A correspondência de glob e a negação estão habilitadas, então você pode ajustar o que excluir e manter. O exemplo acima limpará tudo dentro de `./wwwroot/libs`, mas manterá quaisquer arquivos `foo.txt`. |
|||
* A seção **mappings** é uma lista de mapeamentos de arquivos/pastas a serem copiados. Este exemplo não copia nenhum recurso em si, mas depende de um pacote padrão. |
|||
|
|||
Um exemplo de configuração de mapeamento é mostrado abaixo: |
|||
|
|||
```json |
|||
mappings: { |
|||
"@node_modules/bootstrap/dist/css/bootstrap.css": "@libs/bootstrap/css/", |
|||
"@node_modules/bootstrap/dist/js/bootstrap.bundle.js": "@libs/bootstrap/js/", |
|||
"@node_modules/bootstrap-datepicker/dist/locales/*.*": "@libs/bootstrap-datepicker/locales/", |
|||
"@node_modules/bootstrap-v4-rtl/dist/**/*": "@libs/bootstrap-v4-rtl/dist/" |
|||
} |
|||
``` |
|||
|
|||
#### Comando install-libs |
|||
|
|||
Depois de configurar corretamente o arquivo `abp.resourcemapping.js`, você pode executar o seguinte comando da CLI do ABP no terminal: |
|||
|
|||
````bash |
|||
abp install-libs |
|||
```` |
|||
|
|||
Quando você executar este comando, todos os pacotes copiarão seus próprios recursos para a pasta `wwwroot/libs`. Executar `abp install-libs` é necessário apenas se você fizer uma alteração em suas dependências no arquivo **package.json**. |
|||
|
|||
#### Veja também |
|||
|
|||
* [Empacotamento e Minificação](Bundling-Minification.md) |
|||
* [Tematização](Theming.md) |
|||
@ -0,0 +1,477 @@ |
|||
# Guia de Customização da Interface do Usuário do ASP.NET Core (MVC / Razor Pages) |
|||
|
|||
Este documento explica como substituir a interface do usuário de um módulo de aplicativo dependente [módulo de aplicativo](../../Modules/Index.md) ou [tema](Theming.md) para aplicativos ASP.NET Core MVC / Razor Page. |
|||
|
|||
## Substituindo uma Página |
|||
|
|||
Esta seção aborda o desenvolvimento de [Razor Pages](https://docs.microsoft.com/en-us/aspnet/core/razor-pages/), que é a abordagem recomendada para criar interfaces de usuário renderizadas no servidor para o ASP.NET Core. Os módulos pré-construídos geralmente usam a abordagem Razor Pages em vez do padrão clássico MVC (as próximas seções também abordarão o padrão MVC). |
|||
|
|||
Normalmente, você tem três tipos de requisitos de substituição para uma página: |
|||
|
|||
* Substituir apenas o lado do **Modelo de Página** (C#) para executar lógica adicional sem alterar a interface do usuário da página. |
|||
* Substituir apenas a **Página Razor** (arquivo .chtml) para alterar a interface do usuário sem alterar o código C# por trás da página. |
|||
* **Substituir completamente** a página. |
|||
|
|||
### Substituindo um Modelo de Página (C#) |
|||
|
|||
````csharp |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.Identity.Web.Pages.Identity.Users; |
|||
|
|||
namespace Acme.BookStore.Web.Pages.Identity.Users |
|||
{ |
|||
[Dependency(ReplaceServices = true)] |
|||
[ExposeServices(typeof(EditModalModel))] |
|||
public class MyEditModalModel : EditModalModel |
|||
{ |
|||
public MyEditModalModel( |
|||
IIdentityUserAppService identityUserAppService, |
|||
IIdentityRoleAppService identityRoleAppService |
|||
) : base( |
|||
identityUserAppService, |
|||
identityRoleAppService) |
|||
{ |
|||
} |
|||
|
|||
public async override Task<IActionResult> OnPostAsync() |
|||
{ |
|||
//TODO: Lógica adicional |
|||
await base.OnPostAsync(); |
|||
//TODO: Lógica adicional |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Esta classe herda e substitui o `EditModalModel` para os usuários e substitui o método `OnPostAsync` para executar lógica adicional antes e depois do código subjacente. |
|||
* Ele usa os atributos `ExposeServices` e `Dependency` para substituir a classe. |
|||
|
|||
### Substituindo uma Página Razor (.CSHTML) |
|||
|
|||
Substituir um arquivo `.cshtml` (página razor, visualização razor, componente de visualização... etc.) é possível criando o mesmo arquivo `.cshtml` no mesmo caminho. |
|||
|
|||
#### Exemplo |
|||
|
|||
Este exemplo substitui a interface do usuário da **página de login** definida pelo [Módulo de Conta](../../Modules/Account.md). |
|||
|
|||
O módulo de conta define um arquivo `Login.cshtml` na pasta `Pages/Account`. Portanto, você pode substituí-lo criando um arquivo no mesmo caminho: |
|||
|
|||
 |
|||
|
|||
Normalmente, você deseja copiar o arquivo `.cshtml` original do módulo e fazer as alterações necessárias. Você pode encontrar o arquivo original [aqui](https://github.com/abpframework/abp/blob/dev/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml). Não copie o arquivo `Login.cshtml.cs`, que é o arquivo de código por trás da página razor e não queremos substituí-lo ainda (veja a próxima seção). |
|||
|
|||
> Não se esqueça de adicionar [_ViewImports.cshtml](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/layout?view=aspnetcore-7.0#importing-shared-directives) se a página que você deseja substituir contiver [ABP Tag Helpers](../AspNetCore/Tag-Helpers/Index.md). |
|||
|
|||
````csharp |
|||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling |
|||
```` |
|||
|
|||
Isso é tudo, você pode alterar o conteúdo do arquivo como desejar. |
|||
|
|||
### Substituindo Completamente uma Página Razor |
|||
|
|||
Você pode querer substituir completamente uma página; a página razor e o arquivo C# relacionado à página. |
|||
|
|||
Nesse caso; |
|||
|
|||
1. Substitua a classe do modelo de página C# como descrito acima, mas não substitua a classe de modelo de página existente. |
|||
2. Substitua a Página Razor conforme descrito acima, mas também altere a diretiva @model para apontar para o novo modelo de página. |
|||
|
|||
#### Exemplo |
|||
|
|||
Este exemplo substitui a **página de login** definida pelo [Módulo de Conta](../../Modules/Account.md). |
|||
|
|||
Crie uma classe de modelo de página derivada de `LoginModel` (definida no namespace `Volo.Abp.Account.Web.Pages.Account`): |
|||
|
|||
````csharp |
|||
public class MyLoginModel : LoginModel |
|||
{ |
|||
public MyLoginModel( |
|||
IAuthenticationSchemeProvider schemeProvider, |
|||
IOptions<AbpAccountOptions> accountOptions |
|||
) : base( |
|||
schemeProvider, |
|||
accountOptions) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public override Task<IActionResult> OnPostAsync(string action) |
|||
{ |
|||
//TODO: Adicionar lógica |
|||
return base.OnPostAsync(action); |
|||
} |
|||
|
|||
//TODO: Adicionar novos métodos e propriedades... |
|||
} |
|||
```` |
|||
|
|||
Você pode substituir qualquer método ou adicionar novas propriedades/métodos, se necessário. |
|||
|
|||
> Observe que não usamos `[Dependency(ReplaceServices = true)]` ou `[ExposeServices(typeof(LoginModel))]` porque não queremos substituir a classe existente na injeção de dependência, definimos uma nova. |
|||
|
|||
Copie o arquivo `Login.cshtml` para a sua solução conforme descrito acima. Altere a diretiva **@model** para apontar para o `MyLoginModel`: |
|||
|
|||
````xml |
|||
@page |
|||
... |
|||
@model Acme.BookStore.Web.Pages.Account.MyLoginModel |
|||
... |
|||
```` |
|||
|
|||
Isso é tudo! Faça qualquer alteração na visualização e execute seu aplicativo. |
|||
|
|||
#### Substituindo o Modelo de Página Sem Herança |
|||
|
|||
Você não precisa herdar da classe de modelo de página original (como feito no exemplo anterior). Em vez disso, você pode **reimplementar completamente** a página você mesmo. Nesse caso, basta derivar de `PageModel`, `AbpPageModel` ou qualquer classe base adequada que você precise. |
|||
|
|||
## Substituindo um Componente de Visualização |
|||
|
|||
O ABP Framework, temas pré-construídos e módulos definem alguns **componentes de visualização reutilizáveis**. Esses componentes de visualização podem ser substituídos da mesma forma que uma página descrita acima. |
|||
|
|||
### Exemplo |
|||
|
|||
A captura de tela abaixo foi tirada do [Tema Básico](Basic-Theme.md) fornecido com o modelo de inicialização do aplicativo. |
|||
|
|||
 |
|||
|
|||
O [Tema Básico](Basic-Theme.md) define alguns componentes de visualização para o layout. Por exemplo, a área destacada com o retângulo vermelho acima é chamada de **componente de marca**. Você provavelmente deseja personalizar esse componente adicionando seu **próprio logotipo do aplicativo**. Vamos ver como fazer isso. |
|||
|
|||
Primeiro, crie seu logotipo e coloque-o em uma pasta em seu aplicativo da web. Usamos o caminho `wwwroot/logos/bookstore-logo.png`. Em seguida, copie a visualização do componente de marca ([aqui](https://github.com/abpframework/abp/blob/dev/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Brand/Default.cshtml)) dos arquivos do tema básico na pasta `Themes/Basic/Components/Brand`. O resultado deve ser semelhante à imagem abaixo: |
|||
|
|||
 |
|||
|
|||
Em seguida, altere o `Default.cshtml` como desejar. O conteúdo de exemplo pode ser assim: |
|||
|
|||
````xml |
|||
<a href="/"> |
|||
<img src="~/logos/bookstore-logo.png" width="250" height="60"/> |
|||
</a> |
|||
```` |
|||
|
|||
Agora, você pode executar o aplicativo para ver o resultado: |
|||
|
|||
 |
|||
|
|||
Se necessário, você também pode substituir [o arquivo c# de código por trás](https://github.com/abpframework/abp/blob/dev/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Brand/MainNavbarBrandViewComponent.cs) do componente usando o sistema de injeção de dependência. |
|||
|
|||
### Substituindo o Tema |
|||
|
|||
Assim como explicado acima, você pode substituir qualquer componente, layout ou classe c# do tema usado. Consulte o documento [tematização](Theming.md) para obter mais informações sobre o sistema de tematização. |
|||
|
|||
## Substituindo Recursos Estáticos |
|||
|
|||
Substituir um recurso estático incorporado (como arquivos JavaScript, CSS ou de imagem) de um módulo é bastante fácil. Basta colocar um arquivo no mesmo caminho em sua solução e deixar o [Sistema de Arquivos Virtual](../../Virtual-File-System.md) lidar com ele. |
|||
|
|||
## Manipulando os Pacotes |
|||
|
|||
O sistema de [Empacotamento e Minificação](Bundling-Minification.md) fornece um sistema **extensível e dinâmico** para criar pacotes de **scripts** e **estilos**. Ele permite que você estenda e manipule os pacotes existentes. |
|||
|
|||
### Exemplo: Adicionar um Arquivo CSS Global |
|||
|
|||
Por exemplo, o ABP Framework define um **pacote de estilo global** que é adicionado a todas as páginas (na verdade, adicionado ao layout pelos temas). Vamos adicionar um **arquivo de estilo personalizado** ao final dos arquivos do pacote, para que possamos substituir qualquer estilo global. |
|||
|
|||
Primeiro, crie um arquivo CSS e coloque-o em uma pasta dentro do `wwwroot`: |
|||
|
|||
 |
|||
|
|||
Defina algumas regras CSS personalizadas dentro do arquivo. Exemplo: |
|||
|
|||
````css |
|||
.card-title { |
|||
color: orange; |
|||
font-size: 2em; |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
.btn-primary { |
|||
background-color: red; |
|||
} |
|||
```` |
|||
|
|||
Em seguida, adicione este arquivo ao pacote global de estilo padrão no método `ConfigureServices` do seu [módulo](../../Module-Development-Basics.md): |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.StyleBundles.Configure( |
|||
StandardBundles.Styles.Global, //O nome do pacote! |
|||
bundleConfiguration => |
|||
{ |
|||
bundleConfiguration.AddFiles("/styles/my-global-styles.css"); |
|||
} |
|||
); |
|||
}); |
|||
```` |
|||
|
|||
#### O Pacote de Script Global |
|||
|
|||
Assim como o `StandardBundles.Styles.Global`, há um `StandardBundles.Scripts.Global` que você pode adicionar arquivos ou manipular os existentes. |
|||
|
|||
### Exemplo: Manipular os Arquivos do Pacote |
|||
|
|||
O exemplo acima adiciona um novo arquivo ao pacote. Você pode fazer mais se criar uma classe de **contribuinte de pacote**. Exemplo: |
|||
|
|||
````csharp |
|||
public class MyGlobalStyleBundleContributor : BundleContributor |
|||
{ |
|||
public override void ConfigureBundle(BundleConfigurationContext context) |
|||
{ |
|||
context.Files.Clear(); |
|||
context.Files.Add("/styles/my-global-styles.css"); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Em seguida, você pode adicionar o contribuinte a um pacote existente: |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.StyleBundles.Configure( |
|||
StandardBundles.Styles.Global, |
|||
bundleConfiguration => |
|||
{ |
|||
bundleConfiguration.AddContributors(typeof(MyGlobalStyleBundleContributor)); |
|||
} |
|||
); |
|||
}); |
|||
```` |
|||
|
|||
Não é uma boa ideia limpar todos os arquivos CSS. Em um cenário do mundo real, você pode encontrar e substituir um arquivo específico pelo seu próprio arquivo. |
|||
|
|||
### Exemplo: Adicionar um Arquivo JavaScript para uma Página Específica |
|||
|
|||
Os exemplos acima funcionam com o pacote global adicionado ao layout. E se você quiser adicionar um arquivo CSS/JavaScript (ou substituir um arquivo) para uma página específica definida em um módulo dependente? |
|||
|
|||
Suponha que você queira executar um código **JavaScript** assim que o usuário entrar na página de **Gerenciamento de Funções** do Módulo de Identidade. |
|||
|
|||
Primeiro, crie um arquivo JavaScript padrão no `wwwroot`, `Pages` ou `Views` (o ABP suporta adicionar recursos estáticos dentro dessas pastas por padrão). Preferimos a pasta `Pages/Identity/Roles` para seguir as convenções: |
|||
|
|||
 |
|||
|
|||
O conteúdo do arquivo é simples: |
|||
|
|||
````js |
|||
$(function() { |
|||
abp.log.info('Meu arquivo de script de função personalizado foi carregado!'); |
|||
}); |
|||
```` |
|||
|
|||
Em seguida, adicione este arquivo ao pacote da página de gerenciamento de funções: |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.ScriptBundles |
|||
.Configure( |
|||
typeof(Volo.Abp.Identity.Web.Pages.Identity.Roles.IndexModel).FullName, |
|||
bundleConfig => |
|||
{ |
|||
bundleConfig.AddFiles("/Pages/Identity/Roles/my-role-script.js"); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
`typeof(Volo.Abp.Identity.Web.Pages.Identity.Roles.IndexModel).FullName` é a maneira segura de obter o nome do pacote para a página de gerenciamento de funções. |
|||
|
|||
> Observe que nem todas as páginas definem esses pacotes de página. Eles definem apenas se necessário. |
|||
|
|||
Além de adicionar um novo arquivo CSS/JavaScript a uma página, você também pode substituir o existente (definindo um contribuinte de pacote). |
|||
|
|||
## Customização do Layout |
|||
|
|||
Os layouts são definidos pelo tema ([consulte a documentação de tematização](Theming.md)) por design. Eles não estão incluídos em uma solução de aplicativo baixada. Dessa forma, você pode facilmente **atualizar** o tema e obter novos recursos. Você não pode **alterar diretamente** o código do layout em seu aplicativo, a menos que o substitua por seu próprio layout (será explicado nas próximas seções). |
|||
|
|||
Existem algumas maneiras comuns de **personalizar o layout** descritas nas seções a seguir. |
|||
|
|||
### Contribuintes de Menu |
|||
|
|||
Existem dois **menus padrão** definidos pelo ABP Framework: |
|||
|
|||
 |
|||
|
|||
* `StandardMenus.Main`: O menu principal do aplicativo. |
|||
* `StandardMenus.User`: O menu do usuário (geralmente no canto superior direito da tela). |
|||
|
|||
A renderização dos menus é de responsabilidade do tema, mas os **itens do menu** são determinados pelos módulos e pelo código do seu aplicativo. Basta implementar a interface `IMenuContributor` e **manipular os itens do menu** no método `ConfigureMenuAsync`. |
|||
|
|||
Os contribuintes de menu são executados sempre que precisam renderizar o menu. Já existe um contribuinte de menu definido no **modelo de inicialização do aplicativo**, para que você possa usá-lo como exemplo e melhorar, se necessário. Consulte o documento [menu de navegação](Navigation-Menu.md) para obter mais informações. |
|||
|
|||
### Contribuintes de Barra de Ferramentas |
|||
|
|||
O sistema de [barra de ferramentas](Toolbars.md) é usado para definir **barras de ferramentas** na interface do usuário. Os módulos (ou seu aplicativo) podem adicionar **itens** a uma barra de ferramentas e, em seguida, o tema renderiza a barra de ferramentas no **layout**. |
|||
|
|||
Existe apenas uma **barra de ferramentas padrão** (chamada "Principal" - definida como uma constante: `StandardToolbars.Main`). Para o tema básico, ele é renderizado como mostrado abaixo: |
|||
|
|||
Na captura de tela acima, existem dois itens adicionados à barra de ferramentas principal: componente de troca de idioma e menu do usuário. Você pode adicionar seus próprios itens aqui. |
|||
|
|||
#### Exemplo: Adicionar um Ícone de Notificação |
|||
|
|||
Neste exemplo, adicionaremos um **ícone de notificação (sino)** à esquerda do item de troca de idioma. Um item na barra de ferramentas deve ser um **componente de visualização**. Portanto, primeiro, crie um novo componente de visualização em seu projeto: |
|||
|
|||
 |
|||
|
|||
**NotificationViewComponent.cs** |
|||
|
|||
````csharp |
|||
public class NotificationViewComponent : AbpViewComponent |
|||
{ |
|||
public async Task<IViewComponentResult> InvokeAsync() |
|||
{ |
|||
return View("/Pages/Shared/Components/Notification/Default.cshtml"); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
**Default.cshtml** |
|||
|
|||
````xml |
|||
<div id="MainNotificationIcon" style="color: white; margin: 8px;"> |
|||
<i class="far fa-bell"></i> |
|||
</div> |
|||
```` |
|||
|
|||
Agora, podemos criar uma classe que implementa a interface `IToolbarContributor`: |
|||
|
|||
````csharp |
|||
public class MyToolbarContributor : IToolbarContributor |
|||
{ |
|||
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context) |
|||
{ |
|||
if (context.Toolbar.Name == StandardToolbars.Main) |
|||
{ |
|||
context.Toolbar.Items |
|||
.Insert(0, new ToolbarItem(typeof(NotificationViewComponent))); |
|||
} |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Esta classe adiciona o `NotificationViewComponent` como o primeiro item na barra de ferramentas `Main`. |
|||
|
|||
Finalmente, você precisa adicionar este contribuinte ao `AbpToolbarOptions`, no `ConfigureServices` do seu módulo: |
|||
|
|||
````csharp |
|||
Configure<AbpToolbarOptions>(options => |
|||
{ |
|||
options.Contributors.Add(new MyToolbarContributor()); |
|||
}); |
|||
```` |
|||
|
|||
Isso é tudo, você verá o ícone de notificação na barra de ferramentas quando executar o aplicativo: |
|||
|
|||
 |
|||
|
|||
O `NotificationViewComponent` neste exemplo simplesmente retorna uma visualização sem nenhum dado. Na vida real, você provavelmente desejará **consultar o banco de dados** (ou chamar uma API HTTP) para obter notificações e passá-las para a visualização. Se necessário, você pode adicionar um arquivo `JavaScript` ou `CSS` ao pacote global (como descrito anteriormente) para o item da barra de ferramentas. |
|||
|
|||
Consulte o documento [barras de ferramentas](Toolbars.md) para obter mais informações sobre o sistema de barras de ferramentas. |
|||
|
|||
### Hooks de Layout |
|||
|
|||
O sistema de [Hooks de Layout](Layout-Hooks.md) permite que você **adicione código** em algumas partes específicas do layout. Todos os layouts de todos os temas devem implementar esses hooks. Em seguida, você pode adicionar um **componente de visualização** em um ponto de hook. |
|||
|
|||
#### Exemplo: Adicionar Script do Google Analytics |
|||
|
|||
Suponha que você precise adicionar o script do Google Analytics ao layout (que estará disponível para todas as páginas). Primeiro, **crie um componente de visualização** em seu projeto: |
|||
|
|||
 |
|||
|
|||
**GoogleAnalyticsViewComponent.cs** |
|||
|
|||
````csharp |
|||
public class GoogleAnalyticsViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View("/Pages/Shared/Components/GoogleAnalytics/Default.cshtml"); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
**Default.cshtml** |
|||
|
|||
````html |
|||
<script> |
|||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ |
|||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), |
|||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) |
|||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
|||
|
|||
ga('create', 'UA-xxxxxx-1', 'auto'); |
|||
ga('send', 'pageview'); |
|||
</script> |
|||
```` |
|||
|
|||
Altere `UA-xxxxxx-1` para o seu próprio código. |
|||
|
|||
Você pode então adicionar este componente a qualquer um dos pontos de hook no `ConfigureServices` do seu módulo: |
|||
|
|||
````csharp |
|||
Configure<AbpLayoutHookOptions>(options => |
|||
{ |
|||
options.Add( |
|||
LayoutHooks.Head.Last, //O nome do hook |
|||
typeof(GoogleAnalyticsViewComponent) //O componente a ser adicionado |
|||
); |
|||
}); |
|||
```` |
|||
|
|||
Agora, o código do GA será inserido no `head` da página como o último item. Você (ou os módulos que você está usando) pode adicionar vários itens ao mesmo hook. Todos eles serão adicionados ao layout. |
|||
|
|||
A configuração acima adiciona o `GoogleAnalyticsViewComponent` a todos os layouts. Talvez você queira adicionar apenas a um layout específico: |
|||
|
|||
````csharp |
|||
Configure<AbpLayoutHookOptions>(options => |
|||
{ |
|||
options.Add( |
|||
LayoutHooks.Head.Last, |
|||
typeof(GoogleAnalyticsViewComponent), |
|||
layout: StandardLayouts.Application //Defina o layout a ser adicionado |
|||
); |
|||
}); |
|||
```` |
|||
|
|||
Consulte a seção de layouts abaixo para saber mais sobre o sistema de layout. |
|||
|
|||
### Layouts |
|||
|
|||
O sistema de layout permite que os temas definam layouts padrão e nomeados e permite que qualquer página selecione um layout adequado para seu propósito. Existem três layouts predefinidos: |
|||
|
|||
* "**Application**": O layout principal (e o padrão) para um aplicativo. Normalmente, contém cabeçalho, menu (barra lateral), rodapé, barra de ferramentas... etc. |
|||
* "**Account**": Este layout é usado para login, registro e outras páginas semelhantes. É usado para as páginas na pasta `/Pages/Account` por padrão. |
|||
* "**Empty**": Layout vazio e mínimo. |
|||
|
|||
Esses nomes são definidos na classe `StandardLayouts` como constantes. Você pode definitivamente criar seus próprios layouts, mas esses são os nomes padrão dos layouts e são implementados por todos os temas por padrão. |
|||
|
|||
#### Localização do Layout |
|||
|
|||
Você pode encontrar os arquivos de layout [aqui](https://github.com/abpframework/abp/blob/dev/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts) para o tema básico. Você pode usá-los como referência para criar seus próprios layouts ou pode substituí-los, se necessário. |
|||
|
|||
#### ITheme |
|||
|
|||
O ABP Framework usa o serviço `ITheme` para obter a localização do layout pelo nome do layout. Você pode substituir este serviço para selecionar dinamicamente a localização do layout. |
|||
|
|||
#### IThemeManager |
|||
|
|||
`IThemeManager` é usado para obter o tema atual e obter o caminho do layout. Qualquer página pode determinar seu próprio layout. Exemplo: |
|||
|
|||
````html |
|||
@using Volo.Abp.AspNetCore.Mvc.UI.Theming |
|||
@inject IThemeManager ThemeManager |
|||
@{ |
|||
Layout = ThemeManager.CurrentTheme.GetLayout(StandardLayouts.Empty); |
|||
} |
|||
```` |
|||
|
|||
Esta página usará o layout vazio. Você usa o método de extensão `ThemeManager.CurrentTheme.GetEmptyLayout();` como atalho. |
|||
|
|||
Se você deseja definir o layout para todas as páginas em uma pasta específica, escreva o código acima em um arquivo `_ViewStart.cshtml` dentro dessa pasta. |
|||
@ -0,0 +1,161 @@ |
|||
# Extensões de Colunas de Tabela de Dados para a Interface do Usuário ASP.NET Core |
|||
|
|||
## Introdução |
|||
|
|||
O sistema de extensão de colunas de tabela de dados permite adicionar uma **nova coluna de tabela** na interface do usuário. O exemplo abaixo adiciona uma nova coluna com o título "Número de Seguro Social": |
|||
|
|||
 |
|||
|
|||
Você pode usar as opções de coluna padrão para controlar a coluna da tabela com precisão. |
|||
|
|||
> Observe que esta é uma API de baixo nível para controlar a coluna da tabela. Se você deseja mostrar uma propriedade de extensão na tabela, consulte o documento [extensão de entidade de módulo](../../Module-Entity-Extensions.md). |
|||
|
|||
## Como Configurar |
|||
|
|||
### Criar um Arquivo JavaScript |
|||
|
|||
Primeiro, adicione um novo arquivo JavaScript à sua solução. Nós adicionamos dentro da pasta `/Pages/Identity/Users` do projeto `.Web`: |
|||
|
|||
 |
|||
|
|||
Aqui está o conteúdo deste arquivo JavaScript: |
|||
|
|||
```js |
|||
abp.ui.extensions.tableColumns |
|||
.get('identity.user') |
|||
.addContributor(function (columnList) { |
|||
columnList.addTail({ //adicionar como a última coluna |
|||
title: 'Número de Seguro Social', |
|||
data: 'extraProperties.SocialSecurityNumber', |
|||
orderable: false, |
|||
render: function (data, type, row) { |
|||
if (row.extraProperties.SocialSecurityNumber) { |
|||
return '<strong>' + |
|||
row.extraProperties.SocialSecurityNumber + |
|||
'<strong>'; |
|||
} else { |
|||
return '<i class="text-muted">indefinido</i>'; |
|||
} |
|||
} |
|||
}); |
|||
}); |
|||
``` |
|||
|
|||
Este exemplo define uma função `render` personalizada para retornar um HTML personalizado para ser renderizado na coluna. |
|||
|
|||
### Adicionar o Arquivo à Página de Gerenciamento de Usuários |
|||
|
|||
Em seguida, você precisa adicionar este arquivo JavaScript à página de gerenciamento de usuários. Você pode aproveitar o poder do sistema de [Agrupamento e Minificação](https://docs.abp.io/en/abp/latest/UI/AspNetCore/Bundling-Minification). |
|||
|
|||
Escreva o seguinte código dentro do método `ConfigureServices` da sua classe de módulo: |
|||
|
|||
```csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.ScriptBundles.Configure( |
|||
typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName, |
|||
bundleConfiguration => |
|||
{ |
|||
bundleConfiguration.AddFiles( |
|||
"/Pages/Identity/Users/my-user-extensions.js" |
|||
); |
|||
}); |
|||
}); |
|||
``` |
|||
|
|||
Esta configuração adiciona `my-user-extensions.js` à página de gerenciamento de usuários do Módulo de Identidade. `typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName` é o nome do pacote na página de gerenciamento de usuários. Esta é uma convenção comum usada para todos os módulos comerciais do ABP. |
|||
|
|||
### Renderizando a Coluna |
|||
|
|||
Este exemplo pressupõe que você definiu uma propriedade extra `SocialSecurityNumber` usando o sistema de [extensão de entidade de módulo](../../Module-Entity-Extensions.md). No entanto; |
|||
|
|||
* Você pode adicionar uma nova coluna relacionada a uma propriedade existente do usuário (que não foi adicionada à tabela por padrão). Exemplo: |
|||
|
|||
````js |
|||
abp.ui.extensions.tableColumns |
|||
.get('identity.user') |
|||
.addContributor(function (columnList) { |
|||
columnList.addTail({ |
|||
title: 'Telefone confirmado?', |
|||
data: 'phoneNumberConfirmed', |
|||
render: function (data, type, row) { |
|||
if (row.phoneNumberConfirmed) { |
|||
return '<strong style="color: green">SIM<strong>'; |
|||
} else { |
|||
return '<i class="text-muted">NÃO</i>'; |
|||
} |
|||
} |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
* Você pode adicionar uma nova coluna personalizada que não está relacionada a nenhuma propriedade da entidade, mas sim a uma informação completamente personalizada. Exemplo: |
|||
|
|||
````js |
|||
abp.ui.extensions.tableColumns |
|||
.get('identity.user') |
|||
.addContributor(function (columnList) { |
|||
columnList.addTail({ |
|||
title: 'Coluna personalizada', |
|||
data: {}, |
|||
orderable: false, |
|||
render: function (data) { |
|||
if (data.phoneNumber) { |
|||
return "ligar: " + data.phoneNumber; |
|||
} else { |
|||
return ''; |
|||
} |
|||
} |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
## API |
|||
|
|||
Esta seção explica os detalhes da API JavaScript `abp.ui.extensions.tableColumns`. |
|||
|
|||
### abp.ui.extensions.tableColumns.get(nomeEntidade) |
|||
|
|||
Este método é usado para acessar as colunas da tabela para uma entidade de um módulo específico. Ele recebe um parâmetro: |
|||
|
|||
* **nomeEntidade**: O nome da entidade definido pelo módulo relacionado. |
|||
|
|||
### abp.ui.extensions.tableColumns.get(nomeEntidade).columns |
|||
|
|||
A propriedade `columns` é usada para recuperar uma [lista duplamente encadeada](../Common/Utils/Linked-List.md) de colunas previamente definidas para uma tabela. Todos os contribuidores são executados na ordem para preparar a lista final de colunas. Isso é normalmente chamado pelos módulos para mostrar as colunas na tabela. No entanto, você pode usá-lo se estiver construindo suas próprias interfaces extensíveis. |
|||
|
|||
### abp.ui.extensions.tableColumns.get(nomeEntidade).addContributor(contributeCallback [, order]) |
|||
|
|||
O método `addContributor` cobre todos os cenários, por exemplo, se você deseja adicionar sua coluna em uma posição diferente na lista, alterar ou remover uma coluna existente. `addContributor` tem os seguintes parâmetros: |
|||
|
|||
* **contributeCallback**: Uma função de retorno de chamada que é chamada sempre que a lista de colunas deve ser criada. Você pode modificar livremente a lista de colunas dentro deste método de retorno de chamada. |
|||
* **order** (opcional): A ordem da chamada na lista de chamadas. Sua chamada é adicionada ao final da lista (portanto, você tem a oportunidade de modificar as colunas adicionadas pelos contribuidores anteriores). Você pode definir `0` para adicionar seu contribuidor como o primeiro item. |
|||
|
|||
#### Exemplo |
|||
|
|||
```js |
|||
var myColumnDefinition = { |
|||
title: 'Coluna personalizada', |
|||
data: {}, |
|||
orderable: false, |
|||
render: function(data) { |
|||
if (data.phoneNumber) { |
|||
return "ligar: " + data.phoneNumber; |
|||
} else { |
|||
return ''; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
abp.ui.extensions.tableColumns |
|||
.get('identity.user') |
|||
.addContributor(function (columnList) { |
|||
// Remover um item da lista de ações |
|||
columnList.dropHead(); |
|||
|
|||
// Adicionar um novo item à lista de ações |
|||
columnList.addHead(myColumnDefinition); |
|||
}); |
|||
``` |
|||
|
|||
> `columnList` é uma [lista encadeada](../Common/Utils/Linked-List.md). Você pode usar seus métodos para construir uma lista de colunas da maneira que precisar. |
|||
@ -0,0 +1,298 @@ |
|||
# ASP.NET Core MVC / Razor Pages: Tabelas de Dados |
|||
|
|||
Uma Tabela de Dados (também conhecida como Data Grid) é um componente de interface do usuário para mostrar dados tabulares aos usuários. Existem muitos componentes/bibliotecas de Tabela de Dados e **você pode usar qualquer um que preferir** com o ABP Framework. No entanto, os modelos de inicialização vêm com a biblioteca [DataTables.Net](https://datatables.net/) já **pré-instalada e configurada**. O ABP Framework fornece adaptadores para essa biblioteca e facilita o uso com os endpoints da API. |
|||
|
|||
Uma captura de tela de exemplo da página de gerenciamento de usuários que mostra a lista de usuários em uma tabela de dados: |
|||
|
|||
 |
|||
|
|||
## Integração com o DataTables.Net |
|||
|
|||
Antes de tudo, você pode seguir a documentação oficial para entender como o [DataTables.Net](https://datatables.net/) funciona. Esta seção se concentrará nos complementos e pontos de integração do ABP, em vez de cobrir completamente o uso dessa biblioteca. |
|||
|
|||
### Um Exemplo Rápido |
|||
|
|||
Você pode seguir o [tutorial de desenvolvimento de aplicativos da web](https://docs.abp.io/en/abp/latest/Tutorials/Part-1?UI=MVC) para um exemplo completo de aplicativo que usa o DataTables.Net como Tabela de Dados. Esta seção mostra um exemplo minimalista. |
|||
|
|||
Você não precisa fazer nada para adicionar a biblioteca DataTables.Net à página, pois ela já está adicionada ao [pacote](Bundling-Minification.md) global por padrão. |
|||
|
|||
Primeiro, adicione um `abp-table` como mostrado abaixo, com um `id`: |
|||
|
|||
````html |
|||
<abp-table striped-rows="true" id="BooksTable"></abp-table> |
|||
```` |
|||
|
|||
> `abp-table` é um [Tag Helper](Tag-Helpers/Index.md) definido pelo ABP Framework, mas uma simples tag `<table...>` também funcionaria. |
|||
|
|||
Em seguida, chame o plugin `DataTable` no seletor da tabela: |
|||
|
|||
````js |
|||
var dataTable = $('#BooksTable').DataTable( |
|||
abp.libs.datatables.normalizeConfiguration({ |
|||
serverSide: true, |
|||
paging: true, |
|||
order: [[1, "asc"]], |
|||
searching: false, |
|||
ajax: abp.libs.datatables.createAjax(acme.bookStore.books.book.getList), |
|||
columnDefs: [ |
|||
{ |
|||
title: l('Ações'), |
|||
rowAction: { |
|||
items: |
|||
[ |
|||
{ |
|||
text: l('Editar'), |
|||
action: function (data) { |
|||
///... |
|||
} |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
{ |
|||
title: l('Nome'), |
|||
data: "name" |
|||
}, |
|||
{ |
|||
title: l('Data de Publicação'), |
|||
data: "publishDate", |
|||
render: function (data) { |
|||
return luxon |
|||
.DateTime |
|||
.fromISO(data, { |
|||
locale: abp.localization.currentCulture.name |
|||
}).toLocaleString(); |
|||
} |
|||
}, |
|||
{ |
|||
title: l('Preço'), |
|||
data: "price" |
|||
} |
|||
] |
|||
}) |
|||
); |
|||
```` |
|||
|
|||
O código de exemplo acima usa algumas funcionalidades de integração do ABP que serão explicadas nas próximas seções. |
|||
|
|||
### Normalização de Configuração |
|||
|
|||
A função `abp.libs.datatables.normalizeConfiguration` recebe uma configuração do DataTables e a normaliza para simplificá-la; |
|||
|
|||
* Define a opção `scrollX` como `true`, se não estiver definida. |
|||
* Define o índice `target` para as definições de coluna. |
|||
* Define a opção `language` para [localizar](../../Localization.md) a tabela no idioma atual. |
|||
|
|||
#### Configuração Padrão |
|||
|
|||
`normalizeConfiguration` usa a configuração padrão. Você pode alterar a configuração padrão usando o objeto `abp.libs.datatables.defaultConfigurations`. Exemplo: |
|||
|
|||
````js |
|||
abp.libs.datatables.defaultConfigurations.scrollX = false; |
|||
```` |
|||
|
|||
Aqui estão todas as opções de configuração; |
|||
|
|||
* `scrollX`: `false` por padrão. |
|||
* `dom`: O valor padrão é `<"dataTable_filters"f>rt<"row dataTable_footer"<"col-auto"l><"col-auto"i><"col"p>>`. |
|||
* `language`: Uma função que retorna o texto de localização usando o idioma atual. |
|||
|
|||
### Adaptador AJAX |
|||
|
|||
O DataTables.Net possui seu próprio formato de dados esperado ao obter os resultados de uma chamada AJAX para o servidor para obter os dados da tabela. Eles estão especialmente relacionados a como os parâmetros de paginação e ordenação são enviados e recebidos. O ABP Framework também oferece suas próprias convenções para a comunicação [AJAX](JavaScript-API/Ajax.md) cliente-servidor. |
|||
|
|||
O método `abp.libs.datatables.createAjax` (usado no exemplo acima) adapta o formato dos dados de solicitação e resposta e funciona perfeitamente com o sistema [Dynamic JavaScript Client Proxy](Dynamic-JavaScript-Proxies.md). |
|||
|
|||
Isso funciona automaticamente, então na maioria das vezes você não precisa saber como funciona. Consulte o documento [DTO](../../Data-Transfer-Objects.md) se você quiser aprender mais sobre `IPagedAndSortedResultRequest`, `IPagedResult` e outras interfaces padrão e classes DTO base usadas na comunicação cliente-servidor. |
|||
|
|||
O `createAjax` também permite que você personalize os parâmetros de solicitação e manipule as respostas. |
|||
|
|||
**Exemplo:** |
|||
|
|||
````csharp |
|||
var inputAction = function (requestData, dataTableSettings) { |
|||
return { |
|||
id: $('#Id').val(), |
|||
name: $('#Name').val(), |
|||
}; |
|||
}; |
|||
|
|||
var responseCallback = function(result) { |
|||
|
|||
// seu código personalizado. |
|||
|
|||
return { |
|||
recordsTotal: result.totalCount, |
|||
recordsFiltered: result.totalCount, |
|||
data: result.items |
|||
}; |
|||
}; |
|||
|
|||
ajax: abp.libs.datatables.createAjax(acme.bookStore.books.book.getList, inputAction, responseCallback) |
|||
```` |
|||
|
|||
Se você não precisa acessar ou modificar o `requestData` ou o `dataTableSettings`, você pode especificar um objeto simples como segundo parâmetro. |
|||
|
|||
````js |
|||
ajax: abp.libs.datatables.createAjax( |
|||
acme.bookStore.books.book.getList, |
|||
{ id: $('#Id').val(), name: $('#Name').val() } |
|||
) |
|||
```` |
|||
|
|||
### Ações de Linha |
|||
|
|||
`rowAction` é uma opção definida pelo ABP Framework para as definições de coluna para mostrar um botão suspenso para executar ações para uma linha na tabela. |
|||
|
|||
A captura de tela de exemplo abaixo mostra as ações para cada usuário na tabela de gerenciamento de usuários: |
|||
|
|||
 |
|||
|
|||
`rowAction` é definido como parte de uma definição de coluna: |
|||
|
|||
````csharp |
|||
{ |
|||
title: l('Ações'), |
|||
rowAction: { |
|||
//TODO: CONFIGURAÇÃO |
|||
} |
|||
}, |
|||
```` |
|||
|
|||
**Exemplo: Mostrar ações *Editar* e *Excluir* para uma linha de livro** |
|||
|
|||
````js |
|||
{ |
|||
title: l('Ações'), |
|||
rowAction: { |
|||
items: |
|||
[ |
|||
{ |
|||
text: l('Editar'), |
|||
action: function (data) { |
|||
//TODO: Abrir um modal para editar o livro |
|||
} |
|||
}, |
|||
{ |
|||
text: l('Excluir'), |
|||
confirmMessage: function (data) { |
|||
return "Tem certeza de que deseja excluir o livro " + data.record.name; |
|||
}, |
|||
action: function (data) { |
|||
acme.bookStore.books.book |
|||
.delete(data.record.id) |
|||
.then(function() { |
|||
abp.notify.info("Excluído com sucesso!"); |
|||
data.table.ajax.reload(); |
|||
}); |
|||
} |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
```` |
|||
|
|||
#### Itens de Ação |
|||
|
|||
`items` é uma matriz de definições de ação. Uma definição de ação pode ter as seguintes opções; |
|||
|
|||
* `text`: O texto (uma `string`) para esta ação a ser mostrada no menu suspenso de ações. |
|||
* `action`: Uma `function` que é executada quando o usuário clica na ação. A função recebe um argumento `data` que possui os seguintes campos; |
|||
* `data.record`: Este é o objeto de dados relacionado à linha. Você pode acessar os campos de dados como `data.record.id`, `data.record.name`... etc. |
|||
* `data.table`: A instância DataTables. |
|||
* `confirmMessage`: Uma `function` (veja o exemplo acima) que retorna uma mensagem (`string`) para mostrar um diálogo para obter uma confirmação do usuário antes de executar a `action`. Exemplo de diálogo de confirmação: |
|||
|
|||
 |
|||
|
|||
Você pode usar o sistema de [localização](JavaScript-API/Localization.md) para mostrar uma mensagem localizada. |
|||
|
|||
* `visible`: Um `bool` ou uma `function` que retorna um `bool`. Se o resultado for `false`, então a ação não é mostrada no menu suspenso de ações. Isso geralmente é combinado com o sistema de [autorização](JavaScript-API/Auth.md) para ocultar a ação se o usuário não tiver permissão para executar essa ação. Exemplo: |
|||
|
|||
````js |
|||
visible: abp.auth.isGranted('BookStore.Books.Delete'); |
|||
```` |
|||
|
|||
Se você definir uma `function`, então a `function` tem dois argumentos: `record` (o objeto de dados da linha relacionada) e a `table` (a instância DataTables). Portanto, você pode decidir mostrar/ocultar a ação dinamicamente, com base nos dados da linha e em outras condições. |
|||
|
|||
* `iconClass`: Pode ser usado para mostrar um ícone de fonte, como um ícone [Font-Awesome](https://fontawesome.com/) (ex: `fas fa-trash-alt`), próximo ao texto da ação. Captura de tela de exemplo: |
|||
|
|||
 |
|||
|
|||
* `enabled`: Uma `function` que retorna um `bool` para desabilitar a ação. A `function` recebe um objeto `data` com dois campos: `data.record` é o objeto de dados relacionado à linha e `data.table` é a instância DataTables. |
|||
* `displayNameHtml`: Defina isso como `true` se o valor `text` contiver tags HTML. |
|||
|
|||
Existem algumas regras com os itens de ação; |
|||
|
|||
* Se nenhum dos itens de ação for visível, a coluna de ações não será renderizada. |
|||
|
|||
### Formato de Dados |
|||
|
|||
#### O Problema |
|||
|
|||
Veja a coluna *Data de Criação* no exemplo abaixo: |
|||
|
|||
````js |
|||
{ |
|||
title: l('CreationTime'), |
|||
data: "creationTime", |
|||
render: function (data) { |
|||
return luxon |
|||
.DateTime |
|||
.fromISO(data, { |
|||
locale: abp.localization.currentCulture.name |
|||
}).toLocaleString(luxon.DateTime.DATETIME_SHORT); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
O `render` é uma opção padrão do DataTables para renderizar o conteúdo da coluna por uma função personalizada. Este exemplo usa a biblioteca [luxon](https://moment.github.io/luxon/) (que é instalada por padrão) para escrever um valor legível por humanos do `creationTime` no idioma atual do usuário. Exemplo de saída da coluna: |
|||
|
|||
 |
|||
|
|||
Se você não definir a opção de renderização, o resultado será feio e não amigável ao usuário: |
|||
|
|||
 |
|||
|
|||
No entanto, renderizar um `DateTime` é quase o mesmo e repetir a mesma lógica de renderização em todos os lugares vai contra o princípio DRY (Don't Repeat Yourself!). |
|||
|
|||
#### Opção dataFormat |
|||
|
|||
A opção `dataFormat` da coluna especifica o formato de dados que é usado para renderizar os dados da coluna. A mesma saída poderia ser alcançada usando a seguinte definição de coluna: |
|||
|
|||
````js |
|||
{ |
|||
title: l('CreationTime'), |
|||
data: "creationTime", |
|||
dataFormat: 'datetime' |
|||
} |
|||
```` |
|||
|
|||
`dataFormat: 'datetime'` especifica o formato de dados para esta coluna. Existem alguns `dataFormat`s pré-definidos: |
|||
|
|||
* `boolean`: Mostra um ícone de `check` para o valor `true` e um ícone de `times` para o valor `false` e é útil para renderizar valores `bool`. |
|||
* `date`: Mostra a parte da data de um valor `DateTime`, formatado com base na cultura atual. |
|||
* `datetime`: Mostra a data e a hora (excluindo segundos) de um valor `DateTime`, formatado com base na cultura atual. |
|||
|
|||
### Renderizadores Padrão |
|||
|
|||
A opção `abp.libs.datatables.defaultRenderers` permite que você defina novos formatos de dados e defina renderizadores para eles. |
|||
|
|||
**Exemplo: Renderizar ícones de masculino/feminino com base no gênero** |
|||
|
|||
````js |
|||
abp.libs.datatables.defaultRenderers['gender'] = function(value) { |
|||
if (value === 'f') { |
|||
return '<i class="fa fa-venus"></i>'; |
|||
} else { |
|||
return '<i class="fa fa-mars"></i>'; |
|||
} |
|||
}; |
|||
```` |
|||
|
|||
Supondo que os valores possíveis para os dados de uma coluna sejam `f` e `m`, o formato de dados `gender` mostra ícones femininos/masculinos em vez dos textos `f` e `m`. Agora você pode definir `dataFormat: 'gender'` para uma definição de coluna que tenha os valores de dados adequados. |
|||
|
|||
> Você pode escrever os renderizadores padrão em um único arquivo JavaScript e adicioná-lo ao [Pacote de Scripts Global](Bundling-Minification.md), para que você possa reutilizá-los em todas as páginas. |
|||
|
|||
## Outras Tabelas de Dados |
|||
|
|||
Você pode usar qualquer biblioteca que preferir. Por exemplo, [veja este artigo](https://community.abp.io/articles/using-devextreme-components-with-the-abp-framework-zb8z7yqv) para aprender como usar o DevExtreme Data Grid em seus aplicativos. |
|||
@ -0,0 +1,97 @@ |
|||
# Proxies de Cliente de API JavaScript Dinâmico |
|||
|
|||
É comum consumir suas APIs HTTP a partir do seu código JavaScript. Para fazer isso, normalmente você lida com chamadas AJAX de baixo nível, como $.ajax, ou melhor [abp.ajax](JavaScript-API/Ajax.md). O ABP Framework fornece **uma maneira melhor** de chamar suas APIs HTTP a partir do seu código JavaScript: Proxies de Cliente de API JavaScript! |
|||
|
|||
## Proxies de Cliente JavaScript Estáticos vs Dinâmicos |
|||
|
|||
O ABP fornece **dois tipos** de sistema de geração de proxy de cliente. Este documento explica os **proxies de cliente dinâmicos**, que geram proxies do lado do cliente em tempo de execução. Você também pode ver a documentação de [Proxies de Cliente de API JavaScript Estáticos](Static-JavaScript-Proxies.md) para aprender como gerar proxies em tempo de desenvolvimento. |
|||
|
|||
A geração de proxy de cliente em tempo de desenvolvimento (estático) tem uma **ligeira vantagem de desempenho**, pois não precisa obter a definição da API HTTP em tempo de execução. No entanto, você deve **regenerar** o código do proxy de cliente sempre que alterar a definição do ponto de extremidade da API. Por outro lado, os proxies de cliente dinâmicos são gerados em tempo de execução e oferecem uma **experiência de desenvolvimento mais fácil**. |
|||
|
|||
## Um Exemplo Rápido |
|||
|
|||
Suponha que você tenha um serviço de aplicativo definido como mostrado abaixo: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace Acme.BookStore.Authors |
|||
{ |
|||
public interface IAuthorAppService : IApplicationService |
|||
{ |
|||
Task<AuthorDto> GetAsync(Guid id); |
|||
|
|||
Task<PagedResultDto<AuthorDto>> GetListAsync(GetAuthorListDto input); |
|||
|
|||
Task<AuthorDto> CreateAsync(CreateAuthorDto input); |
|||
|
|||
Task UpdateAsync(Guid id, UpdateAuthorDto input); |
|||
|
|||
Task DeleteAsync(Guid id); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
> Você pode seguir o [tutorial de desenvolvimento de aplicativos da web](../../Tutorials/Part-1.md) para aprender como criar [serviços de aplicativos](../../Application-Services.md), expô-los como [APIs HTTP](../../API/Auto-API-Controllers.md) e consumir do código JavaScript como um exemplo completo. |
|||
|
|||
Você pode chamar qualquer um dos métodos como se estivesse chamando uma função JavaScript. A função JavaScript tem o mesmo **nome**, **parâmetros** e **valor de retorno** do método C#. |
|||
|
|||
**Exemplo: Obter a lista de autores** |
|||
|
|||
````js |
|||
acme.bookStore.authors.author.getList({ |
|||
maxResultCount: 10 |
|||
}).then(function(result){ |
|||
console.log(result.items); |
|||
}); |
|||
```` |
|||
|
|||
**Exemplo: Excluir um autor** |
|||
|
|||
```js |
|||
acme.bookStore.authors.author |
|||
.delete('7245a066-5457-4941-8aa7-3004778775f0') //Obtenha o id de algum lugar! |
|||
.then(function() { |
|||
abp.notify.info('Excluído com sucesso!'); |
|||
}); |
|||
``` |
|||
|
|||
## Detalhes do AJAX |
|||
|
|||
As funções de proxy de cliente JavaScript usam o [abp.ajax](JavaScript-API/Ajax.md) por baixo dos panos. Portanto, você tem os mesmos benefícios, como **tratamento automático de erros**. Além disso, você pode controlar totalmente a chamada AJAX fornecendo as opções. |
|||
|
|||
### O Valor de Retorno |
|||
|
|||
Cada função retorna um [objeto Deferred](https://api.jquery.com/category/deferred-object/). Isso significa que você pode encadear com `then` para obter o resultado, `catch` para lidar com o erro, `always` para executar uma ação assim que a operação for concluída (com sucesso ou falha). |
|||
|
|||
### Opções do AJAX |
|||
|
|||
Cada função recebe um **último parâmetro** adicional após seus próprios parâmetros. O último parâmetro é chamado de `ajaxParams`. É um objeto que substitui as opções do AJAX. |
|||
|
|||
**Exemplo: Definir as opções do AJAX `type` e `dataType`** |
|||
|
|||
````js |
|||
acme.bookStore.authors.author |
|||
.delete('7245a066-5457-4941-8aa7-3004778775f0', { |
|||
type: 'POST', |
|||
dataType: 'xml' |
|||
}) |
|||
.then(function() { |
|||
abp.notify.info('Excluído com sucesso!'); |
|||
}); |
|||
```` |
|||
|
|||
Consulte a documentação do [jQuery.ajax](https://api.jquery.com/jQuery.ajax/) para todas as opções disponíveis. |
|||
|
|||
## Endpoint do Script de Proxy de Serviço |
|||
|
|||
A mágica é feita pelo endpoint `/Abp/ServiceProxyScript` definido pelo ABP Framework e adicionado automaticamente ao layout. Você pode visitar este endpoint em sua aplicação para ver as definições das funções de proxy de cliente. Este arquivo de script é gerado automaticamente pelo ABP Framework com base nas definições dos métodos do lado do servidor e nos detalhes do ponto de extremidade HTTP relacionado. |
|||
|
|||
## Veja Também |
|||
|
|||
* [Proxies de Cliente de API JavaScript Estáticos](Static-JavaScript-Proxies.md) |
|||
* [Controladores de API Automáticos](../../API/Auto-API-Controllers.md) |
|||
* [Tutorial de Desenvolvimento de Aplicativos da Web](../../Tutorials/Part-1.md) |
|||
@ -0,0 +1,108 @@ |
|||
# Extensões de Ação de Entidade para a Interface do Usuário do ASP.NET Core |
|||
|
|||
## Introdução |
|||
|
|||
O sistema de extensão de ação de entidade permite adicionar uma **nova ação** ao menu de ações de uma entidade. Uma ação **Clique em Mim** foi adicionada à página de *Gerenciamento de Usuários* abaixo: |
|||
|
|||
 |
|||
|
|||
Você pode executar qualquer ação (abrir um modal, fazer uma chamada de API HTTP, redirecionar para outra página... etc) escrevendo seu código personalizado. Você pode acessar a entidade atual em seu código. |
|||
|
|||
## Como Configurar |
|||
|
|||
Neste exemplo, adicionaremos uma ação "Clique em Mim!" e executaremos um código JavaScript para a página de gerenciamento de usuários do [Módulo de Identidade](../../Modules/Identity.md). |
|||
|
|||
### Criar um Arquivo JavaScript |
|||
|
|||
Primeiro, adicione um novo arquivo JavaScript à sua solução. Nós adicionamos dentro da pasta `/Pages/Identity/Users` do projeto `.Web`: |
|||
|
|||
 |
|||
|
|||
Aqui está o conteúdo deste arquivo JavaScript: |
|||
|
|||
```js |
|||
var clickMeAction = { |
|||
text: 'Clique em Mim!', |
|||
action: function(data) { |
|||
//TODO: Escreva seu código personalizado |
|||
alert(data.record.userName); |
|||
} |
|||
}; |
|||
|
|||
abp.ui.extensions.entityActions |
|||
.get('identity.user') |
|||
.addContributor(function(actionList) { |
|||
actionList.addTail(clickMeAction); |
|||
}); |
|||
``` |
|||
|
|||
Na função `action`, você pode fazer qualquer coisa que precisar. Consulte a seção API para obter um uso detalhado. |
|||
|
|||
### Adicionar o Arquivo à Página de Gerenciamento de Usuários |
|||
|
|||
Em seguida, você precisa adicionar este arquivo JavaScript à página de gerenciamento de usuários. Você pode aproveitar o poder do [Sistema de Agrupamento e Minificação](Bundling-Minification.md). |
|||
|
|||
Escreva o seguinte código dentro do método `ConfigureServices` da sua classe de módulo: |
|||
|
|||
```csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.ScriptBundles.Configure( |
|||
typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName, |
|||
bundleConfiguration => |
|||
{ |
|||
bundleConfiguration.AddFiles( |
|||
"/Pages/Identity/Users/my-user-extensions.js" |
|||
); |
|||
}); |
|||
}); |
|||
``` |
|||
|
|||
Essa configuração adiciona `my-user-extensions.js` à página de gerenciamento de usuários do Módulo de Identidade. `typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName` é o nome do pacote na página de gerenciamento de usuários. Essa é uma convenção comum usada para todos os módulos comerciais do ABP. |
|||
|
|||
Isso é tudo. Execute sua aplicação para ver o resultado. |
|||
|
|||
## API |
|||
|
|||
Esta seção explica os detalhes da API JavaScript `abp.ui.extensions.entityActions`. |
|||
|
|||
### abp.ui.extensions.entityActions.get(entityName) |
|||
|
|||
Este método é usado para acessar as ações de entidade de um módulo específico. Ele recebe um parâmetro: |
|||
|
|||
* **entityName**: O nome da entidade definido pelo módulo relacionado. |
|||
|
|||
### abp.ui.extensions.entityActions.get(entityName).actions |
|||
|
|||
A propriedade `actions` é usada para recuperar uma [lista duplamente encadeada](../Common/Utils/Linked-List.md) de ações previamente definidas para uma entidade. Todos os contribuidores são executados para preparar a lista final de ações. Isso é normalmente chamado pelos módulos para mostrar as ações na grade. No entanto, você pode usá-lo se estiver construindo suas próprias interfaces extensíveis. |
|||
|
|||
### abp.ui.extensions.entityActions.get(entityName).addContributor(contributeCallback) |
|||
|
|||
O método `addContributor` cobre todos os cenários, por exemplo, se você deseja adicionar sua ação em uma posição diferente na lista, alterar ou remover um item de ação existente. `addContributor` com o seguinte parâmetro: |
|||
|
|||
* **contributeCallback**: Uma função de retorno de chamada que é chamada sempre que a lista de ações deve ser criada. Você pode modificar livremente a lista de ações dentro deste método de retorno de chamada. |
|||
|
|||
#### Exemplo |
|||
|
|||
```js |
|||
var clickMe2Action = { |
|||
text: 'Clique em Mim 2!', |
|||
icon: 'fas fa-hand-point-right', |
|||
action: function(data) { |
|||
//TODO: Escreva seu código personalizado |
|||
alert(data.record.userName); |
|||
} |
|||
}; |
|||
|
|||
abp.ui.extensions.entityActions |
|||
.get('identity.user') |
|||
.addContributor(function(actionList) { |
|||
// Remover um item da actionList |
|||
actionList.dropHead(); |
|||
|
|||
// Adicionar o novo item à actionList |
|||
actionList.addHead(clickMe2Action); |
|||
}); |
|||
``` |
|||
|
|||
> `actionList` é uma [lista encadeada](../Common/Utils/Linked-List.md). Você pode usar seus métodos para construir uma lista de colunas da maneira que precisar. |
|||
@ -0,0 +1,227 @@ |
|||
# ASP.NET Core MVC / Razor Pages: Formulários e Validação |
|||
|
|||
O ABP Framework fornece infraestrutura e convenções para facilitar a criação de formulários, localizar nomes de exibição para os elementos do formulário e lidar com validação no lado do servidor e do cliente; |
|||
|
|||
* O helper de tag [abp-dynamic-form](Tag-Helpers/Dynamic-Forms.md) automatiza a criação de um **formulário completo** a partir de uma classe de modelo C#: cria os elementos de entrada, lida com a localização e validação no lado do cliente. |
|||
* Os helpers de tag [ABP Form](Tag-Helpers/Form-elements.md) (`abp-input`, `abp-select`, `abp-radio`...) renderizam **um único elemento de formulário** com localização e validação no lado do cliente. |
|||
* O ABP Framework automaticamente **localiza o nome de exibição** de um elemento do formulário sem a necessidade de adicionar um atributo `[DisplayName]`. |
|||
* Os **erros de validação** são automaticamente localizados com base na cultura do usuário. |
|||
|
|||
> Este documento é para a **validação no lado do cliente** e não cobre a validação no lado do servidor. Verifique o [documento de validação](../../Validation.md) para a infraestrutura de validação no lado do servidor. |
|||
|
|||
## O Modo Clássico |
|||
|
|||
Em uma típica interface de usuário ASP.NET Core MVC / Razor Pages baseada no Bootstrap, você [precisa escrever](https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation#client-side-validation) um código boilerplate como este para criar um elemento de formulário simples: |
|||
|
|||
````html |
|||
<div class="form-group"> |
|||
<label asp-for="Movie.ReleaseDate" class="control-label"></label> |
|||
<input asp-for="Movie.ReleaseDate" class="form-control" /> |
|||
<span asp-validation-for="Movie.ReleaseDate" class="text-danger"></span> |
|||
</div> |
|||
```` |
|||
|
|||
Você pode continuar usando essa abordagem se precisar ou preferir. No entanto, os helpers de tag do ABP Form podem produzir a mesma saída com um código mínimo. |
|||
|
|||
## ABP Dynamic Forms |
|||
|
|||
O helper de tag [abp-dynamic-form](Tag-Helpers/Dynamic-Forms.md) automatiza completamente a criação do formulário. Considere esta classe de modelo como exemplo: |
|||
|
|||
```csharp |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
|||
|
|||
namespace MyProject.Web.Pages |
|||
{ |
|||
public class MovieViewModel |
|||
{ |
|||
[Required] |
|||
[StringLength(256)] |
|||
public string Name { get; set; } |
|||
|
|||
[Required] |
|||
[DataType(DataType.Date)] |
|||
public DateTime ReleaseDate { get; set; } |
|||
|
|||
[Required] |
|||
[TextArea] |
|||
[StringLength(1000)] |
|||
public string Description { get; set; } |
|||
|
|||
public Genre Genre { get; set; } |
|||
|
|||
public float? Price { get; set; } |
|||
|
|||
public bool PreOrder { get; set; } |
|||
} |
|||
} |
|||
``` |
|||
|
|||
Ele usa os atributos de anotação de dados para definir regras de validação e estilos de UI para as propriedades. `Genre` é um `enum` neste exemplo: |
|||
|
|||
````csharp |
|||
namespace MyProject.Web.Pages |
|||
{ |
|||
public enum Genre |
|||
{ |
|||
Classic, |
|||
Action, |
|||
Fiction, |
|||
Fantasy, |
|||
Animation |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Para criar o formulário em uma página razor, crie uma propriedade na sua classe `PageModel`: |
|||
|
|||
```csharp |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.RazorPages; |
|||
|
|||
namespace MyProject.Web.Pages |
|||
{ |
|||
public class CreateMovieModel : PageModel |
|||
{ |
|||
[BindProperty] |
|||
public MovieViewModel Movie { get; set; } |
|||
|
|||
public void OnGet() |
|||
{ |
|||
Movie = new MovieViewModel(); |
|||
} |
|||
|
|||
public async Task OnPostAsync() |
|||
{ |
|||
if (ModelState.IsValid) |
|||
{ |
|||
//TODO: Salvar o Filme |
|||
} |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
Em seguida, você pode renderizar o formulário no arquivo `.cshtml`: |
|||
|
|||
```html |
|||
@page |
|||
@model MyProject.Web.Pages.CreateMovieModel |
|||
|
|||
<h2>Criar um novo Filme</h2> |
|||
|
|||
<abp-dynamic-form abp-model="Movie" submit-button="true" /> |
|||
``` |
|||
|
|||
O resultado é mostrado abaixo: |
|||
|
|||
 |
|||
|
|||
Consulte a seção *Localização e Validação* abaixo para localizar os nomes de exibição dos campos e ver como a validação funciona. |
|||
|
|||
> Consulte [seu próprio documento](Tag-Helpers/Dynamic-Forms.md) para todas as opções do helper de tag `abp-dynamic-form`. |
|||
|
|||
## ABP Form Tag Helpers |
|||
|
|||
O `abp-dynamic-form` cobre a maioria dos cenários e permite controlar e personalizar o formulário usando os atributos. |
|||
|
|||
No entanto, se você quiser **renderizar o corpo do formulário você mesmo** (por exemplo, se você quiser ter controle total sobre o **layout do formulário**), você pode usar diretamente os [ABP Form Tag Helpers](Tag-Helpers/Form-elements.md). O mesmo formulário auto-gerado acima pode ser criado usando os ABP Form Tag Helpers, como mostrado abaixo: |
|||
|
|||
```html |
|||
@page |
|||
@model MyProject.Web.Pages.CreateMovieModel |
|||
|
|||
<h2>Criar um novo Filme</h2> |
|||
|
|||
<form method="post"> |
|||
<abp-input asp-for="Movie.Name"/> |
|||
<abp-input asp-for="Movie.ReleaseDate"/> |
|||
<abp-input asp-for="Movie.Description"/> |
|||
<abp-select asp-for="Movie.Genre"/> |
|||
<abp-input asp-for="Movie.Price"/> |
|||
<abp-input asp-for="Movie.PreOrder"/> |
|||
<abp-button button-type="Primary" type="submit">Salvar</abp-button> |
|||
</form> |
|||
``` |
|||
|
|||
> Consulte o documento [ABP Form Tag Helpers](Tag-Helpers/Form-elements.md) para obter detalhes desses helpers de tag e suas opções. |
|||
|
|||
## Validação e Localização |
|||
|
|||
Tanto o Dynamic Form quanto os Form Tag Helpers **validam automaticamente** a entrada com base nos atributos de anotação de dados e exibem mensagens de erro de validação na interface do usuário. As mensagens de erro são **automaticamente localizadas** com base na cultura atual. |
|||
|
|||
**Exemplo: O usuário deixa vazio uma propriedade de string obrigatória** |
|||
|
|||
 |
|||
|
|||
A mensagem de erro abaixo é mostrada se o idioma for francês: |
|||
|
|||
 |
|||
|
|||
Os erros de validação já estão [traduzidos](https://github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization) em muitos idiomas. Você pode [contribuir](../../Contribution/Index.md) para a tradução do seu próprio idioma ou substituir os textos para sua própria aplicação seguindo a documentação de [localização](../../Localization.md). |
|||
|
|||
## Localização do Nome de Exibição |
|||
|
|||
O ABP Framework usa o nome da propriedade como o nome do campo na interface do usuário. Normalmente, você deseja [localizar](../../Localization.md) esse nome com base na cultura atual. |
|||
|
|||
O ABP Framework pode localizar convencionalmente os campos na interface do usuário quando você adiciona as chaves de localização aos arquivos JSON de localização. |
|||
|
|||
Exemplo: Localização em francês para a propriedade *Name* (adicionar ao `fr.json` na aplicação): |
|||
|
|||
````js |
|||
"Name": "Nom" |
|||
```` |
|||
|
|||
Então, a interface do usuário usará o nome fornecido para o idioma francês: |
|||
|
|||
 |
|||
|
|||
### Usando o Prefixo `DisplayName:` |
|||
|
|||
Usar diretamente o nome da propriedade como chave de localização pode ser um problema se você precisar usar o nome da propriedade para outro propósito, com um valor de tradução diferente. Nesse caso, use o prefixo `DisplayName:` para a chave de localização: |
|||
|
|||
````js |
|||
"DisplayName:Name": "Nom" |
|||
```` |
|||
|
|||
O ABP prefere usar a chave `DisplayName:Name` em vez da chave `Name` se ela existir. |
|||
|
|||
### Usando uma Chave de Localização Personalizada |
|||
|
|||
Se necessário, você pode usar o atributo `[DisplayName]` para especificar a chave de localização para uma propriedade específica: |
|||
|
|||
````csharp |
|||
[DisplayName("MyNameKey")] |
|||
public string Name { get; set; } |
|||
```` |
|||
|
|||
Nesse caso, você pode adicionar uma entrada ao arquivo de localização usando a chave `MyNameKey`. |
|||
|
|||
> Se você usar o `[DisplayName]` mas não adicionar uma entrada correspondente ao arquivo de localização, o ABP Framework mostrará a chave fornecida como o nome do campo, `MyNameKey` para esse caso. Portanto, ele fornece uma maneira de especificar um nome de exibição codificado mesmo se você não precisar usar o sistema de localização. |
|||
|
|||
### Localização de Enum |
|||
|
|||
Os membros do Enum também são automaticamente localizados sempre que possível. Por exemplo, quando adicionamos `<abp-select asp-for="Movie.Genre"/>` ao formulário (como fizemos na seção *ABP Form Tag Helpers*), o ABP pode preencher automaticamente os nomes localizados dos membros do Enum. Para habilitar isso, você deve definir os valores localizados no arquivo JSON de localização. Exemplo de entradas para o Enum `Genre` definido na seção *ABP Form Tag Helpers*: |
|||
|
|||
````json |
|||
"Enum:Genre.0": "Filme Clássico", |
|||
"Enum:Genre.1": "Filme de Ação", |
|||
"Enum:Genre.2": "Ficção", |
|||
"Enum:Genre.3": "Fantasia", |
|||
"Enum:Genre.4": "Animação/Desenho" |
|||
```` |
|||
|
|||
Você pode usar uma das seguintes sintaxes para as chaves de localização: |
|||
|
|||
* `Enum:<nome-do-tipo-enum>.<valor-do-enum>` |
|||
* `<nome-do-tipo-enum>.<valor-do-enum>` |
|||
|
|||
> Lembre-se de que se você não especificar valores para o seu Enum, os valores serão ordenados, começando em `0`. |
|||
|
|||
> Os helpers de tag do MVC também suportam o uso de nomes de membros do Enum em vez de valores (então, você pode definir `"Enum:Genre.Action"` em vez de `"Enum:Genre.1"`, por exemplo), mas isso não é sugerido. Porque, quando você serializa propriedades Enum para JSON e envia para clientes, o serializador padrão usa os valores Enum em vez dos nomes do Enum. Portanto, o nome do Enum não estará disponível para os clientes, e isso será um problema se você quiser usar os mesmos valores de localização no lado do cliente. |
|||
|
|||
## Veja também |
|||
|
|||
* [Validação no Lado do Servidor](../../Validation.md) |
|||
@ -0,0 +1,150 @@ |
|||
# ASP.NET Core MVC / Páginas Razor UI JavaScript AJAX API |
|||
|
|||
A API `abp.ajax` fornece uma maneira conveniente de realizar chamadas AJAX para o servidor. Ela usa internamente o `$.ajax` do JQuery, mas automatiza algumas tarefas comuns para você: |
|||
|
|||
* Lida automaticamente com os erros e localiza-os, informando o usuário (usando o [abp.message](Message.md)). Então, normalmente você não precisa se preocupar com os erros. |
|||
* Adiciona automaticamente um token de **anti-falsificação** ao cabeçalho HTTP para satisfazer a validação de proteção CSRF no lado do servidor. |
|||
* Define automaticamente as opções padrão e permite configurar as opções padrão em um único local. |
|||
* Pode **bloquear** uma parte da interface do usuário (ou a página inteira) durante a operação AJAX. |
|||
* Permite personalizar completamente qualquer chamada AJAX, usando as opções padrão do `$.ajax`. |
|||
|
|||
> Embora o `abp.ajax` torne a chamada AJAX mais fácil, normalmente você usará o sistema [Dynamic JavaScript Client Proxy](../Dynamic-JavaScript-Proxies.md) para fazer chamadas às suas APIs HTTP do lado do servidor. O `abp.ajax` pode ser usado quando você precisa realizar operações AJAX de baixo nível. |
|||
|
|||
## Uso básico |
|||
|
|||
O `abp.ajax` aceita um objeto de opções que é aceito pelo [$.ajax](https://api.jquery.com/jquery.ajax/#jQuery-ajax-settings) padrão. Todas as opções padrão são válidas. Ele retorna uma [promessa](https://api.jquery.com/category/deferred-object/) como valor de retorno. |
|||
|
|||
**Exemplo: Obter a lista de usuários** |
|||
|
|||
````js |
|||
abp.ajax({ |
|||
type: 'GET', |
|||
url: '/api/identity/users' |
|||
}).then(function(result){ |
|||
console.log(result); |
|||
}); |
|||
```` |
|||
|
|||
Este comando registra a lista de usuários no console, se você estiver **logado** na aplicação e tiver [permissão](../../../Authorization.md) para a página de gerenciamento de usuários do [Módulo de Identidade](../../../Modules/Identity.md). |
|||
|
|||
## Tratamento de erros |
|||
|
|||
A chamada AJAX de exemplo acima mostra uma **mensagem de erro** se você não estiver logado na aplicação ou não tiver as permissões necessárias para realizar essa solicitação: |
|||
|
|||
 |
|||
|
|||
Todos os tipos de erros são tratados automaticamente pelo `abp.ajax`, a menos que você queira desabilitá-lo. |
|||
|
|||
### Resposta de erro padrão |
|||
|
|||
O `abp.ajax` é compatível com o sistema de tratamento de exceções do [ABP Framework](../../../Exception-Handling.md) e lida corretamente com o formato de erro padrão retornado pelo servidor. Uma mensagem de erro típica é um JSON como o abaixo: |
|||
|
|||
````json |
|||
{ |
|||
"error": { |
|||
"code": "App:010042", |
|||
"message": "Este tópico está bloqueado e não é possível adicionar uma nova mensagem", |
|||
"details": "Informações mais detalhadas sobre o erro..." |
|||
} |
|||
} |
|||
```` |
|||
|
|||
A mensagem de erro é mostrada diretamente ao usuário, usando as propriedades `message` e `details`. |
|||
|
|||
### Resposta de erro não padrão e códigos de status HTTP |
|||
|
|||
Ele também lida com erros mesmo se o formato de erro padrão não for enviado pelo servidor. Isso pode acontecer se você ignorar o sistema de tratamento de exceções do ABP e construir manualmente a resposta HTTP no servidor. Nesse caso, os **códigos de status HTTP** são considerados. |
|||
|
|||
Os seguintes códigos de status HTTP são predefinidos: |
|||
|
|||
* **401**: Mostra uma mensagem de erro como "*Você deve estar autenticado (fazer login) para realizar esta operação*". Quando os usuários clicam no botão OK, eles são redirecionados para a página inicial da aplicação para fazer login novamente. |
|||
* **403**: Mostra uma mensagem de erro como "*Você não tem permissão para realizar esta operação*". |
|||
* **404**: Mostra uma mensagem de erro como "*O recurso solicitado não foi encontrado no servidor*". |
|||
* **Outros**: Mostra uma mensagem de erro genérica como "*Ocorreu um erro. Detalhes do erro não enviados pelo servidor*". |
|||
|
|||
Todas essas mensagens são localizadas com base no idioma atual do usuário. |
|||
|
|||
### Tratando manualmente os erros |
|||
|
|||
Como o `abp.ajax` retorna uma promessa, você sempre pode encadear uma chamada `.catch(...)` para registrar um retorno de chamada que é executado se a solicitação AJAX falhar. |
|||
|
|||
**Exemplo: Mostrar um alerta se a solicitação AJAX falhar** |
|||
|
|||
````js |
|||
abp.ajax({ |
|||
type: 'GET', |
|||
url: '/api/identity/users' |
|||
}).then(function(result){ |
|||
console.log(result); |
|||
}).catch(function(){ |
|||
alert("solicitação falhou :("); |
|||
}); |
|||
```` |
|||
|
|||
Enquanto seu retorno de chamada é executado, o ABP ainda trata o erro por si só. Se você quiser desabilitar o tratamento automático de erros, passe `abpHandleError: false` nas opções do `abp.ajax`. |
|||
|
|||
**Exemplo: Desabilitar o tratamento automático de erros** |
|||
|
|||
````js |
|||
abp.ajax({ |
|||
type: 'GET', |
|||
url: '/api/identity/users', |
|||
abpHandleError: false // DESABILITAR O TRATAMENTO AUTOMÁTICO DE ERROS |
|||
}).then(function(result){ |
|||
console.log(result); |
|||
}).catch(function(){ |
|||
alert("solicitação falhou :("); |
|||
}); |
|||
```` |
|||
|
|||
Se você definir `abpHandleError: false` e não capturar o erro você mesmo, então o erro será ocultado e a solicitação falhará silenciosamente. O `abp.ajax` ainda registra o erro no console do navegador (consulte a seção *Configuração* para substituí-lo). |
|||
|
|||
## Configuração |
|||
|
|||
O `abp.ajax` possui uma **configuração global** que você pode personalizar com base em seus requisitos. |
|||
|
|||
### Opções padrão do AJAX |
|||
|
|||
O objeto `abp.ajax.defaultOpts` é usado para configurar as opções padrão usadas ao realizar uma chamada AJAX, a menos que você as substitua. O valor padrão deste objeto é mostrado abaixo: |
|||
|
|||
````js |
|||
{ |
|||
dataType: 'json', |
|||
type: 'POST', |
|||
contentType: 'application/json', |
|||
headers: { |
|||
'X-Requested-With': 'XMLHttpRequest' |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Portanto, se você quiser alterar o tipo de solicitação padrão, pode fazer da seguinte forma: |
|||
|
|||
````js |
|||
abp.ajax.defaultOpts.type = 'GET'; |
|||
```` |
|||
|
|||
Escreva este código antes de todo o seu código JavaScript. Normalmente, você deseja colocar essa configuração em um arquivo JavaScript separado e adicioná-lo ao layout usando o [bundle](../Bundling-Minification.md) global. |
|||
|
|||
### Registrar/Mostrar erros |
|||
|
|||
As seguintes funções podem ser substituídas para personalizar o registro e a exibição das mensagens de erro: |
|||
|
|||
* A função `abp.ajax.logError` registra os erros usando o [abp.log.error(...)](Logging.md) por padrão. |
|||
* A função `abp.ajax.showError` mostra a mensagem de erro usando o [abp.message.error(...)](Message.md) por padrão. |
|||
* A função `abp.ajax.handleErrorStatusCode` trata diferentes códigos de status HTTP e mostra mensagens diferentes com base no código. |
|||
* A função `abp.ajax.handleAbpErrorResponse` trata os erros enviados com o formato de erro padrão do ABP. |
|||
* A função `abp.ajax.handleNonAbpErrorResponse` trata as respostas de erro não padrão. |
|||
* A função `abp.ajax.handleUnAuthorizedRequest` trata as respostas com o código de status `401` e redireciona os usuários para a página inicial da aplicação. |
|||
|
|||
**Exemplo: Substituir a função `logError`** |
|||
|
|||
````js |
|||
abp.ajax.logError = function(error) { |
|||
//... |
|||
} |
|||
```` |
|||
|
|||
### Outras opções |
|||
|
|||
* A função `abp.ajax.ajaxSendHandler` é usada para interceptar as solicitações AJAX e adicionar um token de anti-falsificação ao cabeçalho HTTP. Observe que isso funciona para todas as solicitações AJAX, mesmo se você não usar o `abp.ajax`. |
|||
@ -0,0 +1,23 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: JavaScript Auth API |
|||
|
|||
A API de autenticação permite que você verifique as permissões (políticas) para o usuário atual no lado do cliente. Dessa forma, você pode mostrar/ocultar partes da interface do usuário condicionalmente ou executar sua lógica no lado do cliente com base nas permissões atuais. |
|||
|
|||
> Este documento explica apenas a API JavaScript. Consulte o [documento de autorização](../../../Authorization.md) para entender o sistema de autorização e permissão do ABP. |
|||
|
|||
## Uso básico |
|||
|
|||
A função `abp.auth.isGranted(...)` é usada para verificar se uma permissão/política foi concedida ou não: |
|||
|
|||
````js |
|||
if (abp.auth.isGranted('DeleteUsers')) { |
|||
//TODO: Excluir o usuário |
|||
} else { |
|||
alert("Você não tem permissão para excluir um usuário!"); |
|||
} |
|||
```` |
|||
|
|||
## Outros campos e funções |
|||
|
|||
* `abp.auth.isAnyGranted(...)`: Recebe um ou mais nomes de permissão/política e retorna `true` se pelo menos um deles foi concedido. |
|||
* `abp.auth.areAllGranted(...)`: Recebe um ou mais nomes de permissão/política e retorna `true` se todos eles foram concedidos. |
|||
* `abp.auth.grantedPolicies`: Este é um objeto onde as chaves são os nomes de permissão/política. Aqui você pode encontrar os nomes de permissão/política concedidos. |
|||
@ -0,0 +1,56 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Bloqueio/Busy em JavaScript |
|||
|
|||
A API de Bloqueio desabilita (bloqueia) a página ou uma parte da página. |
|||
|
|||
## Uso Básico |
|||
|
|||
**Exemplo: Bloquear (desabilitar) a página completa** |
|||
|
|||
````js |
|||
abp.ui.block(); |
|||
```` |
|||
|
|||
**Exemplo: Bloquear (desabilitar) um elemento HTML** |
|||
|
|||
````js |
|||
abp.ui.block('#MyContainer'); |
|||
```` |
|||
|
|||
**Exemplo: Habilitar novamente o elemento ou página previamente bloqueados:** |
|||
|
|||
````js |
|||
abp.ui.unblock(); |
|||
```` |
|||
|
|||
## Opções |
|||
|
|||
O método `abp.ui.block()` pode receber um objeto de opções que pode conter os seguintes campos: |
|||
|
|||
* `elm`: Um seletor opcional para encontrar o elemento a ser bloqueado (por exemplo, `#MyContainerId`). Se não for fornecido, a página inteira será bloqueada. O seletor também pode ser passado diretamente para o método `block()` como mostrado acima. |
|||
* `busy`: Defina como `true` para mostrar um indicador de progresso na área bloqueada. |
|||
* `promise`: Um objeto de promessa com callbacks `always` ou `finally`. Isso pode ser útil se você quiser desbloquear automaticamente a área bloqueada quando uma operação adiada for concluída. |
|||
|
|||
**Exemplo: Bloquear um elemento com indicador de ocupado** |
|||
|
|||
````js |
|||
abp.ui.block({ |
|||
elm: '#MySection', |
|||
busy: true |
|||
}); |
|||
```` |
|||
|
|||
A interface resultante será parecida com a seguinte: |
|||
|
|||
 |
|||
|
|||
## setBusy |
|||
|
|||
`abp.ui.setBusy(...)` e `abp.ui.clearBusy()` são funções de atalho se você quiser usar o bloqueio com a opção `busy`. |
|||
|
|||
**Exemplo: Bloquear com ocupado** |
|||
|
|||
````js |
|||
abp.ui.setBusy('#MySection'); |
|||
```` |
|||
|
|||
Então você pode usar `abp.ui.clearBusy();` para reabilitar a área/página ocupada. |
|||
@ -0,0 +1,49 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API JavaScript do Usuário Atual |
|||
|
|||
`abp.currentUser` é um objeto que contém informações sobre o usuário atual da aplicação. |
|||
|
|||
> Este documento explica apenas a API JavaScript. Consulte o documento [CurrentUser](../../../CurrentUser.md) para obter informações sobre o usuário atual no lado do servidor. |
|||
|
|||
## Usuário Autenticado |
|||
|
|||
Se o usuário estiver autenticado, este objeto será algo como abaixo: |
|||
|
|||
````js |
|||
{ |
|||
isAuthenticated: true, |
|||
id: "34f1f4a7-13cc-4b91-84d1-b91c87afa95f", |
|||
tenantId: null, |
|||
userName: "john", |
|||
name: "John", |
|||
surName: "Nash", |
|||
email: "john.nash@abp.io", |
|||
emailVerified: true, |
|||
phoneNumber: null, |
|||
phoneNumberVerified: false, |
|||
roles: ["moderator","supporter"] |
|||
} |
|||
```` |
|||
|
|||
Portanto, `abp.currentUser.userName` retorna `john` neste caso. |
|||
|
|||
## Usuário Anônimo |
|||
|
|||
Se o usuário não estiver autenticado, este objeto será algo como abaixo: |
|||
|
|||
````js |
|||
{ |
|||
isAuthenticated: false, |
|||
id: null, |
|||
tenantId: null, |
|||
userName: null, |
|||
name: null, |
|||
surName: null, |
|||
email: null, |
|||
emailVerified: false, |
|||
phoneNumber: null, |
|||
phoneNumberVerified: false, |
|||
roles: [] |
|||
} |
|||
```` |
|||
|
|||
Você pode verificar `abp.currentUser.isAuthenticated` para entender se o usuário está autenticado ou não. |
|||
@ -0,0 +1,116 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API DOM JavaScript |
|||
|
|||
`abp.dom` (Document Object Model) fornece eventos aos quais você pode se inscrever para ser notificado quando elementos são adicionados e removidos dinamicamente da página (DOM). |
|||
|
|||
Isso é especialmente útil se você deseja inicializar os novos elementos carregados. Isso geralmente é necessário quando você adiciona elementos dinamicamente ao DOM (por exemplo, obtém alguns elementos HTML via AJAX) após a inicialização da página. |
|||
|
|||
> O ABP usa o [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) para observar as alterações feitas no DOM. |
|||
|
|||
## Eventos de Nó |
|||
|
|||
### onNodeAdded |
|||
|
|||
Esse evento é acionado quando um elemento é adicionado ao DOM. Exemplo: |
|||
|
|||
````js |
|||
abp.dom.onNodeAdded(function(args){ |
|||
console.log(args.$el); |
|||
}); |
|||
```` |
|||
|
|||
O objeto `args` possui os seguintes campos: |
|||
|
|||
* `$el`: A seleção JQuery para obter o novo elemento inserido no DOM. |
|||
|
|||
### onNodeRemoved |
|||
|
|||
Esse evento é acionado quando um elemento é removido do DOM. Exemplo: |
|||
|
|||
````js |
|||
abp.dom.onNodeRemoved(function(args){ |
|||
console.log(args.$el); |
|||
}); |
|||
```` |
|||
|
|||
O objeto `args` possui os seguintes campos: |
|||
|
|||
* `$el`: A seleção JQuery para obter o elemento removido do DOM. |
|||
|
|||
## Inicializadores Pré-Construídos |
|||
|
|||
O ABP Framework usa os eventos DOM para inicializar algum tipo de elementos HTML quando eles são adicionados ao DOM após a inicialização da página. |
|||
|
|||
> Observe que os mesmos inicializadores também funcionam se esses elementos já estiverem incluídos no DOM inicial. Portanto, se eles forem carregados inicialmente ou de forma tardia, eles funcionam como esperado. |
|||
|
|||
### Inicializador de Formulário |
|||
|
|||
O inicializador de formulário (definido como `abp.dom.initializers.initializeForms`) inicializa os formulários carregados de forma tardia; |
|||
|
|||
* Habilita automaticamente a validação `unobtrusive` no formulário. |
|||
* Pode mostrar automaticamente uma mensagem de confirmação quando você envia o formulário. Para habilitar esse recurso, basta adicionar o atributo `data-confirm` com uma mensagem (como `data-confirm="Tem certeza?"`) ao elemento `form`. |
|||
* Se o elemento `form` tiver o atributo `data-ajaxForm="true"`, então chama automaticamente o `.abpAjaxForm()` no elemento `form`, para enviar o formulário via AJAX. |
|||
|
|||
Consulte o documento [Forms & Validation](../Forms-Validation.md) para mais informações. |
|||
|
|||
### Inicializador de Script |
|||
|
|||
O inicializador de script (`abp.dom.initializers.initializeScript`) pode executar um código JavaScript para um elemento DOM. |
|||
|
|||
**Exemplo: Carregar de forma tardia um componente e executar algum código quando o elemento for carregado** |
|||
|
|||
Suponha que você tenha um contêiner para carregar o elemento dentro: |
|||
|
|||
````html |
|||
<div id="LazyComponent"></div> |
|||
```` |
|||
|
|||
E este é o componente que será carregado via AJAX do servidor e inserido no contêiner: |
|||
|
|||
````html |
|||
<div data-script-class="MyCustomClass"> |
|||
<p>Mensagem de exemplo</p> |
|||
</div> |
|||
```` |
|||
|
|||
`data-script-class="MyCustomClass"` indica a classe JavaScript que será usada para executar alguma lógica nesse elemento: |
|||
|
|||
`MyCustomClass` é um objeto global definido da seguinte forma: |
|||
|
|||
````js |
|||
MyCustomClass = function(){ |
|||
|
|||
function initDom($el){ |
|||
$el.css('color', 'red'); |
|||
} |
|||
|
|||
return { |
|||
initDom: initDom |
|||
} |
|||
}; |
|||
```` |
|||
|
|||
`initDom` é a função que é chamada pelo ABP Framework. O argumento `$el` é o elemento HTML carregado como uma seleção JQuery. |
|||
|
|||
Finalmente, você pode carregar o componente dentro do contêiner após uma chamada AJAX: |
|||
|
|||
````js |
|||
$(function () { |
|||
setTimeout(function(){ |
|||
$.get('/get-my-element').then(function(response){ |
|||
$('#LazyComponent').html(response); |
|||
}); |
|||
}, 2000); |
|||
}); |
|||
```` |
|||
|
|||
O sistema de Inicialização de Script é especialmente útil se você não sabe como e quando o componente será carregado no DOM. Isso pode ser possível se você desenvolveu um componente de IU reutilizável em uma biblioteca e deseja que o desenvolvedor do aplicativo não precise se preocupar com a inicialização do componente em diferentes casos de uso. |
|||
|
|||
> A inicialização de script não funciona se o componente for carregado no DOM inicial. Nesse caso, você é responsável por inicializá-lo. |
|||
|
|||
### Outros Inicializadores |
|||
|
|||
Os seguintes componentes e bibliotecas do Bootstrap são inicializados automaticamente quando são adicionados ao DOM: |
|||
|
|||
* Tooltip |
|||
* Popover |
|||
* Timeago |
|||
@ -0,0 +1,87 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Eventos JavaScript |
|||
|
|||
O objeto `abp.event` é um serviço simples que é usado para publicar e se inscrever em eventos globais **no navegador**. |
|||
|
|||
> Esta API não está relacionada a eventos locais ou distribuídos do lado do servidor. Ela funciona dentro dos limites do navegador para permitir que os componentes da interface do usuário (partes do código) se comuniquem de forma desacoplada. |
|||
|
|||
## Uso Básico |
|||
|
|||
### Publicando Eventos |
|||
|
|||
Use `abp.event.trigger` para publicar eventos. |
|||
|
|||
**Exemplo: Publicar um evento *Basket Updated* (Carrinho Atualizado)** |
|||
|
|||
````js |
|||
abp.event.trigger('basketUpdated'); |
|||
```` |
|||
|
|||
Isso acionará todas as chamadas de retorno inscritas. |
|||
|
|||
### Se inscrevendo nos Eventos |
|||
|
|||
Use `abp.event.on` para se inscrever em eventos. |
|||
|
|||
**Exemplo: Consumir o evento *Basket Updated* (Carrinho Atualizado)** |
|||
|
|||
````js |
|||
abp.event.on('basketUpdated', function() { |
|||
console.log('Manipulou o evento basketUpdated...'); |
|||
}); |
|||
```` |
|||
|
|||
Você começará a receber eventos depois de se inscrever no evento. |
|||
|
|||
### Cancelando a inscrição nos Eventos |
|||
|
|||
Se você precisar cancelar a inscrição em um evento pré-inscrito, poderá usar a função `abp.event.off(eventName, callback)`. Nesse caso, você tem a chamada de retorno como uma declaração de função separada. |
|||
|
|||
**Exemplo: Inscrever e cancelar a inscrição** |
|||
|
|||
````js |
|||
function onBasketUpdated() { |
|||
console.log('Manipulou o evento basketUpdated...'); |
|||
} |
|||
|
|||
//Inscrever |
|||
abp.event.on('basketUpdated', onBasketUpdated); |
|||
|
|||
//Cancelar a inscrição |
|||
abp.event.off('basketUpdated', onBasketUpdated); |
|||
```` |
|||
|
|||
Você não receberá mais eventos depois de cancelar a inscrição no evento. |
|||
|
|||
## Argumentos do Evento |
|||
|
|||
Você pode passar argumentos (de qualquer quantidade) para o método `trigger` e obtê-los na chamada de retorno da inscrição. |
|||
|
|||
**Exemplo: Adicionar o carrinho como argumento do evento** |
|||
|
|||
````js |
|||
//Inscrever-se no evento |
|||
abp.event.on('basketUpdated', function(basket) { |
|||
console.log('O novo objeto do carrinho: '); |
|||
console.log(basket); |
|||
}); |
|||
|
|||
//Acionar o evento |
|||
abp.event.trigger('basketUpdated', { |
|||
items: [ |
|||
{ |
|||
"productId": "123", |
|||
"count": 2 |
|||
}, |
|||
{ |
|||
"productId": "832", |
|||
"count": 1 |
|||
} |
|||
] |
|||
}); |
|||
```` |
|||
|
|||
### Múltiplos Argumentos |
|||
|
|||
Se você deseja passar vários argumentos, pode passar como `abp.event.on('basketUpdated', arg0, arg1, agr2)`. Em seguida, você pode adicionar a mesma lista de argumentos à função de chamada de retorno no lado do assinante. |
|||
|
|||
> **Dica:** Alternativamente, você pode enviar um único objeto que possui um campo separado para cada argumento. Isso facilita a extensão/mudança dos argumentos do evento no futuro sem quebrar os assinantes. |
|||
@ -0,0 +1,29 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Recursos JavaScript |
|||
|
|||
A API `abp.features` permite que você verifique recursos ou obtenha os valores dos recursos no lado do cliente. Você pode ler o valor atual de um recurso apenas no lado do cliente se for permitido pela definição do recurso (no lado do servidor). |
|||
|
|||
> Este documento explica apenas a API JavaScript. Consulte o documento [Recursos](../../../Recursos.md) para entender o sistema de Recursos do ABP. |
|||
|
|||
## Uso Básico |
|||
|
|||
````js |
|||
// Obtém um valor como string. |
|||
var valor = abp.features.get('ExportarParaExcel'); |
|||
|
|||
// Verifica se o recurso está habilitado |
|||
var habilitado = abp.features.isEnabled('ExportarParaExcel.Habilitado'); |
|||
```` |
|||
|
|||
## Todos os Valores |
|||
|
|||
`abp.features.values` pode ser usado para acessar todos os valores dos recursos. |
|||
|
|||
Um exemplo de valor desse objeto é mostrado abaixo: |
|||
|
|||
````js |
|||
{ |
|||
Identity.DoisFatores: "Opcional", |
|||
ExportarParaExcel.Habilitado: "true", |
|||
... |
|||
} |
|||
```` |
|||
@ -0,0 +1,24 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Recursos Globais JavaScript |
|||
|
|||
A API `abp.globalFeatures` permite que você obtenha os recursos habilitados dos [Recursos Globais](../../../Global-Features.md) no lado do cliente. |
|||
|
|||
> Este documento apenas explica a API JavaScript. Consulte o documento [Recursos Globais](../../../Global-Features.md) para entender o sistema de Recursos Globais do ABP. |
|||
|
|||
## Uso |
|||
|
|||
````js |
|||
// Obtém todos os recursos globais habilitados. |
|||
> abp.globalFeatures.enabledFeatures |
|||
|
|||
[ 'Shopping.Payment', 'Ecommerce.Subscription' ] |
|||
|
|||
|
|||
// Verifica se o recurso global está habilitado. |
|||
> abp.globalFeatures.isEnabled('Ecommerce.Subscription') |
|||
|
|||
true |
|||
|
|||
> abp.globalFeatures.isEnabled('My.Subscription') |
|||
|
|||
false |
|||
```` |
|||
@ -0,0 +1,20 @@ |
|||
# API JavaScript |
|||
|
|||
ABP fornece um conjunto de APIs JavaScript para aplicações ASP.NET Core MVC / Razor Pages. Elas podem ser usadas para realizar facilmente requisitos comuns de aplicativos no lado do cliente e integrar ao lado do servidor. |
|||
|
|||
## APIs |
|||
|
|||
* [AJAX](Ajax.md) |
|||
* [Auth](Auth.md) |
|||
* [CurrentUser](CurrentUser.md) |
|||
* [DOM](DOM.md) |
|||
* [Events](Events.md) |
|||
* [Features](Features.md) |
|||
* [Global Features](GlobalFeatures.md) |
|||
* [Localization](Localization.md) |
|||
* [Logging](Logging.md) |
|||
* [ResourceLoader](ResourceLoader.md) |
|||
* [Settings](Settings.md) |
|||
* [UI Block/Busy](Block-Busy.md) |
|||
* [UI Message](Message.md) |
|||
* [UI Notification](Notify.md) |
|||
@ -0,0 +1,146 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Localização JavaScript |
|||
|
|||
A API de localização permite que você reutilize os recursos de localização do lado do servidor no lado do cliente. |
|||
|
|||
> Este documento explica apenas a API JavaScript. Consulte o [documento de localização](../../../Localization.md) para entender o sistema de localização do ABP. |
|||
|
|||
## Uso básico |
|||
|
|||
A função `abp.localization.getResource(...)` é usada para obter um recurso de localização: |
|||
|
|||
````js |
|||
var testResource = abp.localization.getResource('Test'); |
|||
```` |
|||
|
|||
Em seguida, você pode localizar uma string com base nesse recurso: |
|||
|
|||
````js |
|||
var str = testResource('HelloWorld'); |
|||
```` |
|||
|
|||
A função `abp.localization.localize(...)` é um atalho onde você pode especificar tanto o nome do texto quanto o nome do recurso: |
|||
|
|||
````js |
|||
var str = abp.localization.localize('HelloWorld', 'Test'); |
|||
```` |
|||
|
|||
`HelloWorld` é o texto a ser localizado, onde `Test` é o nome do recurso de localização aqui. |
|||
|
|||
### Lógica de fallback |
|||
|
|||
Se os textos fornecidos não forem localizados, o método de localização retorna a chave fornecida como resultado da localização. |
|||
|
|||
### Recurso de Localização Padrão |
|||
|
|||
Se você não especificar o nome do recurso de localização, ele usará o **recurso de localização padrão** definido nas `AbpLocalizationOptions` (consulte o [documento de localização](../../../Localization.md)). |
|||
|
|||
**Exemplo: Usando o recurso de localização padrão** |
|||
|
|||
````js |
|||
var str = abp.localization.localize('HelloWorld'); // usa o recurso padrão |
|||
```` |
|||
|
|||
### Argumentos de Formato |
|||
|
|||
Se sua string localizada contiver argumentos, como `Olá {0}, bem-vindo!`, você pode passar argumentos para os métodos de localização. Exemplos: |
|||
|
|||
````js |
|||
var testSource = abp.localization.getResource('Test'); |
|||
var str1 = testSource('HelloWelcomeMessage', 'John'); |
|||
var str2 = abp.localization.localize('HelloWelcomeMessage', 'Test', 'John'); |
|||
```` |
|||
|
|||
Supondo que `HelloWelcomeMessage` seja localizado como `Olá {0}, bem-vindo!`, ambos os exemplos acima produzem a saída `Olá John, bem-vindo!`. |
|||
|
|||
## Outras Propriedades e Métodos |
|||
|
|||
### abp.localization.resources |
|||
|
|||
A propriedade `abp.localization.resources` armazena todos os recursos de localização, chaves e seus valores. |
|||
|
|||
### abp.localization.isLocalized |
|||
|
|||
Retorna um booleano indicando se o texto fornecido foi localizado ou não. |
|||
|
|||
**Exemplo** |
|||
|
|||
````js |
|||
abp.localization.isLocalized('ProductName', 'MyResource'); |
|||
```` |
|||
|
|||
Retorna `true` se o texto `ProductName` foi localizado para o recurso `MyResource`. Caso contrário, retorna `false`. Você pode deixar o nome do recurso vazio para usar o recurso de localização padrão. |
|||
|
|||
### abp.localization.defaultResourceName |
|||
|
|||
`abp.localization.defaultResourceName` pode ser definido para alterar o recurso de localização padrão. Normalmente, você não define isso, pois o ABP Framework o define automaticamente com base na configuração do lado do servidor. |
|||
|
|||
### abp.localization.currentCulture |
|||
|
|||
`abp.localization.currentCulture` retorna um objeto para obter informações sobre o **idioma atualmente selecionado**. |
|||
|
|||
Um exemplo de valor desse objeto é mostrado abaixo: |
|||
|
|||
````js |
|||
{ |
|||
"displayName": "Inglês", |
|||
"englishName": "Inglês", |
|||
"threeLetterIsoLanguageName": "eng", |
|||
"twoLetterIsoLanguageName": "en", |
|||
"isRightToLeft": false, |
|||
"cultureName": "en", |
|||
"name": "en", |
|||
"nativeName": "Inglês", |
|||
"dateTimeFormat": { |
|||
"calendarAlgorithmType": "Calendário Solar", |
|||
"dateTimeFormatLong": "dddd, d 'de' MMMM 'de' yyyy", |
|||
"shortDatePattern": "dd/MM/yyyy", |
|||
"fullDateTimePattern": "dddd, d 'de' MMMM 'de' yyyy HH:mm:ss", |
|||
"dateSeparator": "/", |
|||
"shortTimePattern": "HH:mm", |
|||
"longTimePattern": "HH:mm:ss" |
|||
} |
|||
} |
|||
```` |
|||
|
|||
### abp.localization.languages |
|||
|
|||
Usado para obter a lista de todos os **idiomas disponíveis** na aplicação. Um exemplo de valor desse objeto é mostrado abaixo: |
|||
|
|||
````js |
|||
[ |
|||
{ |
|||
"cultureName": "en", |
|||
"uiCultureName": "en", |
|||
"displayName": "Inglês", |
|||
"flagIcon": null |
|||
}, |
|||
{ |
|||
"cultureName": "fr", |
|||
"uiCultureName": "fr", |
|||
"displayName": "Francês", |
|||
"flagIcon": null |
|||
}, |
|||
{ |
|||
"cultureName": "pt-BR", |
|||
"uiCultureName": "pt-BR", |
|||
"displayName": "Português", |
|||
"flagIcon": null |
|||
}, |
|||
{ |
|||
"cultureName": "tr", |
|||
"uiCultureName": "tr", |
|||
"displayName": "Turco", |
|||
"flagIcon": null |
|||
}, |
|||
{ |
|||
"cultureName": "zh-Hans", |
|||
"uiCultureName": "zh-Hans", |
|||
"displayName": "Chinês Simplificado", |
|||
"flagIcon": null |
|||
} |
|||
] |
|||
```` |
|||
|
|||
## Veja também |
|||
|
|||
* [Tutorial em vídeo](https://abp.io/video-courses/essentials/localization) |
|||
@ -0,0 +1,49 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Registro de JavaScript |
|||
|
|||
A API `abp.log` é usada para escrever logs simples no lado do cliente. |
|||
|
|||
> Os logs são escritos no console, usando o `console.log`, por padrão. |
|||
|
|||
> Este documento é para registro simples no lado do cliente. Consulte o documento [Logging](../../../Logging.md) para o sistema de registro no lado do servidor. |
|||
|
|||
## Uso Básico |
|||
|
|||
Use um dos métodos `abp.log.xxx(...)` com base na gravidade da mensagem de log. |
|||
|
|||
````js |
|||
abp.log.debug("Algum log de debug aqui..."); // Registrando uma mensagem de debug simples |
|||
abp.log.info({ name: "john", age: 42 }); // Registrando um objeto como um log de informação |
|||
abp.log.warn("Uma mensagem de aviso"); // Registrando uma mensagem de aviso |
|||
abp.log.error('Ocorreu um erro...'); // Mensagem de erro |
|||
abp.log.fatal('A conexão de rede foi perdida!'); // Erro fatal |
|||
```` |
|||
|
|||
## Níveis de Log |
|||
|
|||
Existem 5 níveis para uma mensagem de log: |
|||
|
|||
* DEBUG = 1 |
|||
* INFO = 2 |
|||
* WARN = 3 |
|||
* ERROR = 4 |
|||
* FATAL = 5 |
|||
|
|||
Esses são definidos no objeto `abp.log.levels` (como `abp.log.levels.WARN`). |
|||
|
|||
### Alterando o Nível de Log Atual |
|||
|
|||
Você pode controlar o nível de log da seguinte forma: |
|||
|
|||
````js |
|||
abp.log.level = abp.log.levels.WARN; |
|||
```` |
|||
|
|||
O nível de log padrão é `DEBUG`. |
|||
|
|||
### Registrando Especificando o Nível |
|||
|
|||
Em vez de chamar a função `abp.log.info(...)`, você pode usar o `abp.log.log` especificando o nível de log como parâmetro: |
|||
|
|||
````js |
|||
abp.log.log("mensagem de log...", abp.log.levels.INFO); |
|||
```` |
|||
@ -0,0 +1,127 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Mensagens JavaScript |
|||
|
|||
A API de Mensagens é usada para mostrar mensagens agradáveis ao usuário como um diálogo bloqueante. A API de Mensagens é uma abstração fornecida pelo ABP Framework e implementada usando a biblioteca [SweetAlert](https://sweetalert.js.org/) por padrão. |
|||
|
|||
## Exemplo Rápido |
|||
|
|||
Use a função `abp.message.success(...)` para mostrar uma mensagem de sucesso: |
|||
|
|||
````js |
|||
abp.message.success('Suas alterações foram salvas com sucesso!', 'Parabéns'); |
|||
```` |
|||
|
|||
Isso mostrará um diálogo na interface do usuário: |
|||
|
|||
 |
|||
|
|||
## Mensagens Informativas |
|||
|
|||
Existem quatro tipos de funções de mensagem informativa: |
|||
|
|||
* `abp.message.info(...)` |
|||
* `abp.message.success(...)` |
|||
* `abp.message.warn(...)` |
|||
* `abp.message.error(...)` |
|||
|
|||
Todos esses métodos recebem dois parâmetros: |
|||
|
|||
* `message`: A mensagem (`string`) a ser mostrada. |
|||
* `title`: Um título opcional (`string`). |
|||
|
|||
**Exemplo: Mostrar uma mensagem de erro** |
|||
|
|||
````js |
|||
abp.message.error('O número do seu cartão de crédito não é válido!'); |
|||
```` |
|||
|
|||
 |
|||
|
|||
## Mensagem de Confirmação |
|||
|
|||
A função `abp.message.confirm(...)` pode ser usada para obter uma confirmação do usuário. |
|||
|
|||
**Exemplo** |
|||
|
|||
Use o seguinte código para obter um resultado de confirmação do usuário: |
|||
|
|||
````js |
|||
abp.message.confirm('Tem certeza de que deseja excluir a função "admin"?') |
|||
.then(function(confirmed){ |
|||
if(confirmed){ |
|||
console.log('TODO: excluindo a função...'); |
|||
} |
|||
}); |
|||
```` |
|||
|
|||
A interface resultante será como mostrado abaixo: |
|||
|
|||
 |
|||
|
|||
Se o usuário clicou no botão `Sim`, o argumento `confirmed` na função de retorno `then` será `true`. |
|||
|
|||
> "*Tem certeza?*" é o título padrão (localizado com base no idioma atual) e você pode substituí-lo. |
|||
|
|||
### O Valor de Retorno |
|||
|
|||
O valor de retorno da função `abp.message.confirm(...)` é uma promessa, então você pode encadear um retorno de chamada `then` como mostrado acima. |
|||
|
|||
### Parâmetros |
|||
|
|||
A função `abp.message.confirm(...)` possui os seguintes parâmetros: |
|||
|
|||
* `message`: Uma mensagem (string) para mostrar ao usuário. |
|||
* `titleOrCallback` (opcional): Um título ou uma função de retorno de chamada. Se você fornecer uma string, ela será mostrada como título. Se você fornecer uma função de retorno de chamada (que recebe um parâmetro `bool`), ela será chamada com o resultado. |
|||
* `callback` (opcional): Se você passou um título para o segundo parâmetro, pode passar sua função de retorno de chamada como o terceiro parâmetro. |
|||
|
|||
Passar uma função de retorno de chamada é uma alternativa ao retorno de chamada `then` mostrado acima. |
|||
|
|||
**Exemplo: Fornecendo todos os parâmetros e obtendo o resultado com a função de retorno de chamada** |
|||
|
|||
````js |
|||
abp.message.confirm( |
|||
'Tem certeza de que deseja excluir a função "admin"?', |
|||
'Cuidado!', |
|||
function(confirmed){ |
|||
if(confirmed){ |
|||
console.log('TODO: excluindo a função...'); |
|||
} |
|||
}); |
|||
```` |
|||
|
|||
## Configuração do SweetAlert |
|||
|
|||
A API de Mensagens é implementada usando a biblioteca [SweetAlert](https://sweetalert.js.org/) por padrão. Se você deseja alterar sua configuração, pode definir as opções no objeto `abp.libs.sweetAlert.config`. O objeto de configuração padrão é mostrado abaixo: |
|||
|
|||
````js |
|||
{ |
|||
'default': { |
|||
}, |
|||
info: { |
|||
icon: 'info' |
|||
}, |
|||
success: { |
|||
icon: 'success' |
|||
}, |
|||
warn: { |
|||
icon: 'warning' |
|||
}, |
|||
error: { |
|||
icon: 'error' |
|||
}, |
|||
confirm: { |
|||
icon: 'warning', |
|||
title: 'Tem certeza?', |
|||
buttons: ['Cancelar', 'Sim'] |
|||
} |
|||
} |
|||
```` |
|||
|
|||
> "Tem certeza?", "Cancelar" e "Sim" são textos automaticamente localizados com base no idioma atual. |
|||
|
|||
Portanto, se você deseja definir o ícone `warn`, pode definir assim: |
|||
|
|||
````js |
|||
abp.libs.sweetAlert.config.warn.icon = 'error'; |
|||
```` |
|||
|
|||
Consulte a [documentação do SweetAlert](https://sweetalert.js.org/) para todas as opções de configuração. |
|||
@ -0,0 +1,45 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Notificação JavaScript |
|||
|
|||
A API de Notificação é usada para mostrar notificações de interface do usuário no estilo toast, que desaparecem automaticamente para o usuário final. Por padrão, ela é implementada pela biblioteca [Toastr](https://github.com/CodeSeven/toastr). |
|||
|
|||
## Exemplo Rápido |
|||
|
|||
Use a função `abp.notify.success(...)` para mostrar uma mensagem de sucesso: |
|||
|
|||
````js |
|||
abp.notify.success( |
|||
'O produto "Acme Atom Re-Arranger" foi excluído com sucesso.', |
|||
'Produto Excluído' |
|||
); |
|||
```` |
|||
|
|||
Uma mensagem de notificação é exibida na parte inferior direita da página: |
|||
|
|||
 |
|||
|
|||
## Tipos de Notificação |
|||
|
|||
Existem quatro tipos de notificações pré-definidas; |
|||
|
|||
* `abp.notify.success(...)` |
|||
* `abp.notify.info(...)` |
|||
* `abp.notify.warn(...)` |
|||
* `abp.notify.error(...)` |
|||
|
|||
Todos os métodos acima recebem os seguintes parâmetros; |
|||
|
|||
* `message`: Uma mensagem (`string`) para mostrar ao usuário. |
|||
* `title`: Um título opcional (`string`). |
|||
* `options`: Opções adicionais a serem passadas para a biblioteca subjacente, para o Toastr por padrão. |
|||
|
|||
## Configuração do Toastr |
|||
|
|||
A API de notificação é implementada pela biblioteca [Toastr](https://github.com/CodeSeven/toastr) por padrão. Você pode ver suas próprias opções de configuração. |
|||
|
|||
**Exemplo: Mostrar mensagens toast no canto superior direito da página** |
|||
|
|||
````js |
|||
toastr.options.positionClass = 'toast-top-right'; |
|||
```` |
|||
|
|||
> O ABP define essa opção como `toast-bottom-right` por padrão. Você pode substituí-la como mostrado acima. |
|||
@ -0,0 +1,39 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Carregamento de Recursos JavaScript |
|||
|
|||
`abp.ResourceLoader` é um serviço que pode carregar um arquivo JavaScript ou CSS sob demanda. Ele garante que o arquivo seja carregado apenas uma vez, mesmo que seja solicitado várias vezes. |
|||
|
|||
## Carregando Arquivos de Script |
|||
|
|||
A função `abp.ResourceLoader.loadScript(...)` **carrega** um arquivo JavaScript do servidor e o **executa**. |
|||
|
|||
**Exemplo: Carregar um arquivo JavaScript** |
|||
|
|||
````js |
|||
abp.ResourceLoader.loadScript('/Pages/my-script.js'); |
|||
```` |
|||
|
|||
### Parâmetros |
|||
|
|||
A função `loadScript` pode receber três parâmetros; |
|||
|
|||
* `url` (obrigatório, `string`): A URL do arquivo de script a ser carregado. |
|||
* `loadCallback` (opcional, `function`): Uma função de retorno de chamada que é chamada assim que o script é carregado e executado. Nessa função de retorno de chamada, você pode usar com segurança o código no arquivo de script. Essa função de retorno de chamada é chamada mesmo se o arquivo já tiver sido carregado anteriormente. |
|||
* `failCallback` (opcional, `function`): Uma função de retorno de chamada que é chamada se o carregamento do script falhar. |
|||
|
|||
**Exemplo: Fornecer o argumento `loadCallback`** |
|||
|
|||
````js |
|||
abp.ResourceLoader.loadScript('/Pages/my-script.js', function() { |
|||
console.log('carregado com sucesso :)'); |
|||
}); |
|||
```` |
|||
|
|||
## Carregando Arquivos de Estilo |
|||
|
|||
A função `abp.ResourceLoader.loadStyle(...)` adiciona um elemento `link` à `head` do documento para a URL fornecida, para que o arquivo CSS seja carregado automaticamente pelo navegador. |
|||
|
|||
**Exemplo: Carregar um arquivo CSS** |
|||
|
|||
````js |
|||
abp.ResourceLoader.loadStyle('/Pages/my-styles.css'); |
|||
```` |
|||
@ -0,0 +1,32 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: API de Configuração JavaScript |
|||
|
|||
A API de localização permite que você obtenha os valores das configurações no lado do cliente. Você pode ler o valor atual de uma configuração apenas no lado do cliente se isso for permitido pela definição da configuração (no lado do servidor). |
|||
|
|||
> Este documento explica apenas a API JavaScript. Consulte o [documento de configurações](../../../Settings.md) para entender o sistema de configurações do ABP. |
|||
|
|||
## Uso básico |
|||
|
|||
````js |
|||
// Obtém um valor como string. |
|||
var language = abp.setting.get('Abp.Localization.DefaultLanguage'); |
|||
|
|||
// Obtém um valor inteiro. |
|||
var requiredLength = abp.setting.getInt('Abp.Identity.Password.RequiredLength'); |
|||
|
|||
// Obtém um valor booleano. |
|||
var requireDigit = abp.setting.getBoolean('Abp.Identity.Password.RequireDigit'); |
|||
```` |
|||
|
|||
## Todos os valores |
|||
|
|||
`abp.setting.values` pode ser usado para obter todos os valores de configuração como um objeto, onde as propriedades do objeto são os nomes das configurações e os valores das propriedades são os valores das configurações. |
|||
|
|||
Um exemplo de valor desse objeto é mostrado abaixo: |
|||
|
|||
````js |
|||
{ |
|||
Abp.Localization.DefaultLanguage: "en", |
|||
Abp.Timing.TimeZone: "UTC", |
|||
... |
|||
} |
|||
```` |
|||
@ -0,0 +1,105 @@ |
|||
# ASP.NET Core MVC / Razor Pages: Hooks de Layout |
|||
|
|||
O sistema de temas do ABP Framework coloca o layout da página nos pacotes NuGet do [tema](Theming.md). Isso significa que a aplicação final não inclui um `Layout.cshtml`, portanto, você não pode alterar diretamente o código do layout para personalizá-lo. |
|||
|
|||
Você copia o código do tema para a sua solução. Nesse caso, você tem total liberdade para personalizá-lo. No entanto, você não poderá obter atualizações automáticas do tema (atualizando o pacote NuGet do tema). |
|||
|
|||
O ABP Framework oferece diferentes maneiras de [personalizar a interface do usuário](Customization-User-Interface.md). |
|||
|
|||
O **Sistema de Hooks de Layout** permite que você **adicione código** em partes específicas do layout. Todos os layouts de todos os temas devem implementar esses hooks. Por fim, você pode adicionar um **componente de visualização** em um ponto de hook. |
|||
|
|||
## Exemplo: Adicionar Script do Google Analytics |
|||
|
|||
Suponha que você precise adicionar o script do Google Analytics ao layout (que estará disponível para todas as páginas). Primeiro, **crie um componente de visualização** em seu projeto: |
|||
|
|||
 |
|||
|
|||
**NotificationViewComponent.cs** |
|||
|
|||
````csharp |
|||
public class GoogleAnalyticsViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View("/Pages/Shared/Components/GoogleAnalytics/Default.cshtml"); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
**Default.cshtml** |
|||
|
|||
````html |
|||
<script> |
|||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ |
|||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), |
|||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) |
|||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
|||
|
|||
ga('create', 'UA-xxxxxx-1', 'auto'); |
|||
ga('send', 'pageview'); |
|||
</script> |
|||
```` |
|||
|
|||
Altere `UA-xxxxxx-1` pelo seu próprio código. |
|||
|
|||
Em seguida, você pode adicionar esse componente a qualquer um dos pontos de hook no `ConfigureServices` do seu módulo: |
|||
|
|||
````csharp |
|||
Configure<AbpLayoutHookOptions>(options => |
|||
{ |
|||
options.Add( |
|||
LayoutHooks.Head.Last, //O nome do hook |
|||
typeof(GoogleAnalyticsViewComponent) //O componente a ser adicionado |
|||
); |
|||
}); |
|||
```` |
|||
|
|||
Agora, o código do GA será inserido no `head` da página como o último item. |
|||
|
|||
### Especificando o Layout |
|||
|
|||
A configuração acima adiciona o `GoogleAnalyticsViewComponent` a todos os layouts. Talvez você queira adicionar apenas a um layout específico: |
|||
|
|||
````csharp |
|||
Configure<AbpLayoutHookOptions>(options => |
|||
{ |
|||
options.Add( |
|||
LayoutHooks.Head.Last, |
|||
typeof(GoogleAnalyticsViewComponent), |
|||
layout: StandardLayouts.Application //Defina o layout a ser adicionado |
|||
); |
|||
}); |
|||
```` |
|||
|
|||
Consulte a seção *Layouts* abaixo para saber mais sobre o sistema de layout. |
|||
|
|||
## Pontos de Hook de Layout |
|||
|
|||
Existem alguns pontos de hook de layout predefinidos. O `LayoutHooks.Head.Last` usado acima foi um deles. Os pontos de hook padrão são: |
|||
|
|||
* `LayoutHooks.Head.First`: Usado para adicionar um componente como o primeiro item na tag HTML head. |
|||
* `LayoutHooks.Head.Last`: Usado para adicionar um componente como o último item na tag HTML head. |
|||
* `LayoutHooks.Body.First`: Usado para adicionar um componente como o primeiro item na tag HTML body. |
|||
* `LayoutHooks.Body.Last`: Usado para adicionar um componente como o último item na tag HTML body. |
|||
* `LayoutHooks.PageContent.First`: Usado para adicionar um componente logo antes do conteúdo da página (o `@RenderBody()` no layout). |
|||
* `LayoutHooks.PageContent.Last`: Usado para adicionar um componente logo após o conteúdo da página (o `@RenderBody()` no layout). |
|||
|
|||
> Você (ou os módulos que você está usando) pode adicionar **vários itens ao mesmo ponto de hook**. Todos eles serão adicionados ao layout na ordem em que foram adicionados. |
|||
|
|||
## Layouts |
|||
|
|||
O sistema de layout permite que os temas definam layouts padrão e nomeados e permite que qualquer página selecione um layout adequado para o seu propósito. Existem três layouts predefinidos: |
|||
|
|||
* "**Application**": O layout principal (e padrão) para uma aplicação. Normalmente, contém cabeçalho, menu (barra lateral), rodapé, barra de ferramentas, etc. |
|||
* "**Account**": Este layout é usado pelo login, registro e outras páginas semelhantes. É usado para as páginas na pasta `/Pages/Account` por padrão. |
|||
* "**Empty**": Layout vazio e mínimo. |
|||
|
|||
Esses nomes são definidos na classe `StandardLayouts` como constantes. Você pode criar seus próprios layouts, mas esses são os nomes de layout padrão e implementados por todos os temas por padrão. |
|||
|
|||
### Localização do Layout |
|||
|
|||
Você pode encontrar os arquivos de layout [aqui](https://github.com/abpframework/abp/blob/dev/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts) para o tema básico. Você pode usá-los como referência para construir seus próprios layouts ou pode substituí-los, se necessário. |
|||
|
|||
## Veja também |
|||
|
|||
* [Personalizando a Interface do Usuário](Customization-User-Interface.md) |
|||
@ -0,0 +1,412 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: Modais |
|||
|
|||
Embora você possa continuar usando o [método padrão do Bootstrap](https://getbootstrap.com/docs/4.5/components/modal/) para criar, abrir e gerenciar modais em suas aplicações, o ABP Framework fornece uma maneira **flexível** de gerenciar modais, automatizando tarefas comuns para você. |
|||
|
|||
**Exemplo: Um diálogo modal para criar uma nova entidade de função** |
|||
|
|||
 |
|||
|
|||
O ABP Framework oferece os seguintes benefícios para um modal com um formulário dentro dele: |
|||
|
|||
* **Carrega preguiçosamente** o HTML do modal na página e o **remove** do DOM assim que for fechado. Isso facilita o consumo de um diálogo modal reutilizável. Além disso, toda vez que você abrir o modal, ele será um novo modal, para que você não precise lidar com a redefinição do conteúdo do modal. |
|||
* **Dá foco automaticamente** ao primeiro campo de entrada do formulário assim que o modal for aberto. Você também pode especificar isso usando uma `function` ou um seletor `jquery`. |
|||
* Determina automaticamente o **formulário** dentro de um modal e envia o formulário via **AJAX** em vez de uma postagem normal da página. |
|||
* Verifica automaticamente se o formulário dentro do modal **foi alterado, mas não salvo**. Ele avisa o usuário nesse caso. |
|||
* Desabilita automaticamente os botões do modal (salvar e cancelar) até que a operação AJAX seja concluída. |
|||
* Facilita o registro de um **objeto JavaScript que é inicializado** assim que o modal é carregado. |
|||
|
|||
Portanto, você escreve menos código ao lidar com os modais, especialmente os modais com um formulário dentro. |
|||
|
|||
## Uso básico |
|||
|
|||
### Criando um modal como uma página Razor |
|||
|
|||
Para demonstrar o uso, estamos criando uma página Razor simples, chamada `ProductInfoModal.cshtml`, na pasta `/Pages/Products`: |
|||
|
|||
 |
|||
|
|||
**Conteúdo do ProductInfoModal.cshtml:** |
|||
|
|||
````html |
|||
@page |
|||
@model MyProject.Web.Pages.Products.ProductInfoModalModel |
|||
@{ |
|||
Layout = null; |
|||
} |
|||
<abp-modal> |
|||
<abp-modal-header title="Informações do Produto"></abp-modal-header> |
|||
<abp-modal-body> |
|||
<h3>@Model.ProductName</h3> |
|||
<div> |
|||
<img src="@Model.ProductImageUrl" /> |
|||
</div> |
|||
<p> |
|||
@Model.ProductDescription |
|||
</p> |
|||
<p> |
|||
<small><i>Referência: https://acme.com/catalog/</i></small> |
|||
</p> |
|||
</abp-modal-body> |
|||
<abp-modal-footer buttons="Fechar"></abp-modal-footer> |
|||
</abp-modal> |
|||
```` |
|||
|
|||
* Esta página define o `Layout` como `null`, pois mostraremos isso como um modal. Portanto, não é necessário envolvê-lo com um layout. |
|||
* Ele usa o [tag helper abp-modal](Tag-Helpers/Modals.md) para simplificar a criação do código HTML do modal. Você pode usar o código padrão do modal do Bootstrap se preferir. |
|||
|
|||
**Conteúdo do ProductInfoModalModel.cshtml.cs:** |
|||
|
|||
```csharp |
|||
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; |
|||
|
|||
namespace MyProject.Web.Pages.Products |
|||
{ |
|||
public class ProductInfoModalModel : AbpPageModel |
|||
{ |
|||
public string ProductName { get; set; } |
|||
|
|||
public string ProductDescription { get; set; } |
|||
|
|||
public string ProductImageUrl { get; set; } |
|||
|
|||
public void OnGet() |
|||
{ |
|||
ProductName = "Bola de Aço Indestrutível Acme"; |
|||
ProductDescription = "A Bola de Aço Indestrutível Acme é completamente indestrutível, não há nada que possa destruí-la!"; |
|||
ProductImageUrl = "https://acme.com/catalog/acmeindestructo.jpg"; |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
Você pode obter as informações do produto de um banco de dados ou API. Estamos definindo as propriedades codificadas para simplificar. |
|||
|
|||
### Definindo o Modal Manager |
|||
|
|||
Depois de ter um modal, você pode abri-lo em qualquer página usando algum código JavaScript simples. |
|||
|
|||
Primeiro, crie um objeto `abp.ModalManager` definindo o `viewUrl`, no arquivo JavaScript da página que usará o modal: |
|||
|
|||
````js |
|||
var productInfoModal = new abp.ModalManager({ |
|||
viewUrl: '/Products/ProductInfoModal' |
|||
}); |
|||
```` |
|||
|
|||
> Se você só precisa especificar o `viewUrl`, você pode passá-lo diretamente para o construtor `ModalManager`, como um atalho. Exemplo: `new abp.ModalManager('/Products/ProductInfoModal');` |
|||
|
|||
### Abrindo o Modal |
|||
|
|||
Em seguida, abra o modal sempre que precisar: |
|||
|
|||
````js |
|||
productInfoModal.open(); |
|||
```` |
|||
|
|||
Normalmente, você deseja abrir o modal quando algo acontece; Por exemplo, quando o usuário clica em um botão: |
|||
|
|||
````js |
|||
$('#OpenProductInfoModal').click(function(){ |
|||
productInfoModal.open(); |
|||
}); |
|||
```` |
|||
|
|||
O modal resultante será assim: |
|||
|
|||
 |
|||
|
|||
#### Abrindo o Modal com Argumentos |
|||
|
|||
Ao chamar o método `open()`, o `ModalManager` carrega o HTML do modal solicitando-o do `viewUrl`. Você pode passar alguns **parâmetros de string de consulta** para esta URL ao abrir o modal. |
|||
|
|||
**Exemplo: Passando o ID do produto ao abrir o modal** |
|||
|
|||
````js |
|||
productInfoModal.open({ |
|||
productId: 42 |
|||
}); |
|||
```` |
|||
|
|||
Você pode adicionar um parâmetro `productId` ao método `get`: |
|||
|
|||
````csharp |
|||
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; |
|||
|
|||
namespace MyProject.Web.Pages.Products |
|||
{ |
|||
public class ProductInfoModalModel : AbpPageModel |
|||
{ |
|||
//... |
|||
|
|||
public async Task OnGetAsync(int productId) //Adicione o parâmetro productId |
|||
{ |
|||
//TODO: Obter o produto do banco de dados com o productId fornecido |
|||
//... |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Dessa forma, você pode usar o `productId` para consultar o produto em uma fonte de dados. |
|||
|
|||
## Modais com Formulários |
|||
|
|||
`abp.ModalManager` lida com várias tarefas comuns (descritas na introdução) quando você deseja usar um formulário dentro do modal. |
|||
|
|||
### Exemplo de Modal com um Formulário |
|||
|
|||
Esta seção mostra um exemplo de formulário para criar um novo produto. |
|||
|
|||
#### Criando a Página Razor |
|||
|
|||
Para este exemplo, crie uma nova página Razor, chamada `ProductCreateModal.cshtml`, na pasta `/Pages/Products`: |
|||
|
|||
 |
|||
|
|||
**Conteúdo do ProductCreateModal.cshtml:** |
|||
|
|||
````html |
|||
@page |
|||
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal |
|||
@model MyProject.Web.Pages.Products.ProductCreateModalModel |
|||
@{ |
|||
Layout = null; |
|||
} |
|||
<form method="post" action="@Url.Page("/Products/ProductCreateModal")"> |
|||
<abp-modal> |
|||
<abp-modal-header title="Criar Novo Produto"></abp-modal-header> |
|||
<abp-modal-body> |
|||
<abp-input asp-for="Product.Name"/> |
|||
<abp-input asp-for="Product.Description"/> |
|||
<abp-input asp-for="Product.ReleaseDate"/> |
|||
</abp-modal-body> |
|||
<abp-modal-footer buttons="@AbpModalButtons.Save | @AbpModalButtons.Cancel"></abp-modal-footer> |
|||
</abp-modal> |
|||
</form> |
|||
```` |
|||
|
|||
* O `abp-modal` foi envolvido pelo `form`. Isso é necessário para colocar os botões `Salvar` e `Cancelar` dentro do formulário. Dessa forma, o botão `Salvar` age como o botão `submit` para o `form`. |
|||
* Usamos os [tag helpers abp-input](Tag-Helpers/Form-elements.md) para simplificar a criação dos elementos do formulário. Caso contrário, você precisaria escrever mais HTML. |
|||
|
|||
**Conteúdo do ProductCreateModalModel.cshtml.cs:** |
|||
|
|||
```csharp |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; |
|||
|
|||
namespace MyProject.Web.Pages.Products |
|||
{ |
|||
public class ProductCreateModalModel : AbpPageModel |
|||
{ |
|||
[BindProperty] |
|||
public PoductCreationDto Product { get; set; } |
|||
|
|||
public async Task OnGetAsync() |
|||
{ |
|||
//TODO: Lógica de obtenção, se disponível |
|||
} |
|||
|
|||
public async Task<IActionResult> OnPostAsync() |
|||
{ |
|||
//TODO: Salvar o Produto... |
|||
|
|||
return NoContent(); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
* Esta é uma classe `PageModal` simples. O `[BindProperty]` faz com que o formulário seja vinculado ao modelo quando você envia (submete) o formulário; É o sistema padrão do ASP.NET Core. |
|||
* `OnPostAsync` retorna `NoContent` (este método é definido pela classe base `AbpPageModel`). Porque não precisamos de um valor de retorno no lado do cliente, após a operação de envio do formulário. |
|||
|
|||
**PoductCreationDto:** |
|||
|
|||
`ProductCreateModalModel` usa uma classe `PoductCreationDto` definida da seguinte forma: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
|||
|
|||
namespace MyProject.Web.Pages.Products |
|||
{ |
|||
public class PoductCreationDto |
|||
{ |
|||
[Required] |
|||
[StringLength(128)] |
|||
public string Name { get; set; } |
|||
|
|||
[TextArea(Rows = 4)] |
|||
[StringLength(2000)] |
|||
public string Description { get; set; } |
|||
|
|||
[DataType(DataType.Date)] |
|||
public DateTime ReleaseDate { get; set; } |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* O Tag Helper `abp-input` pode entender os atributos de anotação de dados e usá-los para moldar e validar os elementos do formulário. Consulte o documento [tag helpers abp-input](Tag-Helpers/Form-elements.md) para saber mais. |
|||
|
|||
#### Definindo o Modal Manager |
|||
|
|||
Novamente, crie um objeto `abp.ModalManager` definindo o `viewUrl`, no arquivo JavaScript da página que usará o modal: |
|||
|
|||
````js |
|||
var productCreateModal = new abp.ModalManager({ |
|||
viewUrl: '/Products/ProductCreateModal' |
|||
}); |
|||
```` |
|||
|
|||
#### Abrindo o Modal |
|||
|
|||
Em seguida, abra o modal sempre que precisar: |
|||
|
|||
````js |
|||
productCreateModal.open(); |
|||
```` |
|||
|
|||
Normalmente, você deseja abrir o modal quando algo acontece; Por exemplo, quando o usuário clica em um botão: |
|||
|
|||
````js |
|||
$('#OpenProductCreateModal').click(function(){ |
|||
productCreateModal.open(); |
|||
}); |
|||
```` |
|||
|
|||
Portanto, o código completo será algo assim (supondo que você tenha um `button` com `id` igual a `OpenProductCreateModal` no lado da visualização): |
|||
|
|||
```js |
|||
$(function () { |
|||
|
|||
var productCreateModal = new abp.ModalManager({ |
|||
viewUrl: '/Products/ProductCreateModal' |
|||
}); |
|||
|
|||
$('#OpenProductCreateModal').click(function () { |
|||
productCreateModal.open(); |
|||
}); |
|||
|
|||
}); |
|||
``` |
|||
|
|||
O modal resultante será assim: |
|||
|
|||
 |
|||
|
|||
#### Salvando o Modal |
|||
|
|||
Quando você clica no botão `Salvar`, o formulário é enviado para o servidor. Se o servidor retornar uma **resposta de sucesso**, o evento `onResult` é acionado com alguns argumentos, incluindo a resposta do servidor, e o modal é fechado automaticamente. |
|||
|
|||
Um exemplo de retorno de chamada que registra os argumentos passados para o método `onResult`: |
|||
|
|||
````js |
|||
productCreateModal.onResult(function(){ |
|||
console.log(arguments); |
|||
}); |
|||
```` |
|||
|
|||
Se o servidor retornar uma resposta de falha, ele mostra a mensagem de erro retornada pelo servidor e mantém o modal aberto. |
|||
|
|||
> Consulte a seção *Referência do Modal Manager* abaixo para outros eventos do modal. |
|||
|
|||
#### Cancelando o Modal |
|||
|
|||
Se você clicar no botão Cancelar com algumas alterações feitas, mas não salvas, você receberá uma mensagem de aviso como esta: |
|||
|
|||
 |
|||
|
|||
Se você não deseja essa verificação e mensagem, pode adicionar o atributo `data-check-form-on-close="false"` ao seu elemento `form`. Exemplo: |
|||
|
|||
````html |
|||
<form method="post" |
|||
action="@Url.Page("/Products/ProductCreateModal")" |
|||
data-check-form-on-close="false"> |
|||
```` |
|||
|
|||
### Validação do Formulário |
|||
|
|||
`ModalManager` aciona automaticamente a validação do formulário quando você clica no botão `Salvar` ou pressiona a tecla `Enter` no formulário: |
|||
|
|||
 |
|||
|
|||
Consulte o documento [Forms & Validation](Forms-Validation.md) para saber mais sobre a validação. |
|||
|
|||
## Modais com Arquivos de Script |
|||
|
|||
Você pode precisar executar alguma lógica para o seu modal. Para fazer isso, crie um arquivo JavaScript como abaixo: |
|||
|
|||
````js |
|||
abp.modals.ProductInfo = function () { |
|||
|
|||
function initModal(modalManager, args) { |
|||
var $modal = modalManager.getModal(); |
|||
var $form = modalManager.getForm(); |
|||
|
|||
$modal.find('h3').css('color', 'red'); |
|||
|
|||
console.log('initialized the modal...'); |
|||
}; |
|||
|
|||
return { |
|||
initModal: initModal |
|||
}; |
|||
}; |
|||
```` |
|||
|
|||
* Este código simplesmente adiciona uma classe `ProductInfo` ao namespace `abp.modals`. A classe `ProductInfo` expõe uma única função pública: `initModal`. |
|||
* O método `initModal` é chamado pelo `ModalManager` assim que o HTML do modal é inserido no DOM e está pronto para a lógica de inicialização. |
|||
* O parâmetro `modalManager` é o objeto `ModalManager` relacionado a essa instância do modal. Portanto, você pode usar qualquer função nele em seu código. Consulte a seção *Referência do ModalManager*. |
|||
|
|||
Em seguida, inclua este arquivo na página que você usa o modal: |
|||
|
|||
````html |
|||
<abp-script src="/Pages/Products/ProductInfoModal.js"/> |
|||
<abp-script src="/Pages/Products/Index.js"/> |
|||
```` |
|||
|
|||
* Usamos o `abp-script` Tag Helper aqui. Consulte o documento [Bundling & Minification](Bundling-Minification.md) se você quiser entender isso. Você pode usar a tag `script` padrão. Não importa para este caso. |
|||
|
|||
Por fim, defina a opção `modalClass` ao criar a instância `ModalManager`: |
|||
|
|||
````js |
|||
var productInfoModal = new abp.ModalManager({ |
|||
viewUrl: '/Products/ProductInfoModal', |
|||
modalClass: 'ProductInfo' //Corresponde a abp.modals.ProductInfo |
|||
}); |
|||
```` |
|||
|
|||
### Carregamento Preguiçoso do Arquivo de Script |
|||
|
|||
Em vez de adicionar o `ProductInfoModal.js` à página em que você usa o modal, você pode configurá-lo para carregar preguiçosamente o arquivo de script quando o modal for aberto pela primeira vez. |
|||
|
|||
Exemplo: |
|||
|
|||
````js |
|||
var productInfoModal = new abp.ModalManager({ |
|||
viewUrl: '/Products/ProductInfoModal', |
|||
scriptUrl: '/Pages/Products/ProductInfoModal.js', //URL de carregamento preguiçoso |
|||
modalClass: 'ProductInfo' |
|||
}); |
|||
```` |
|||
|
|||
* `scriptUrl` é usado para definir a URL para carregar o arquivo de script do modal. |
|||
* Nesse caso, você não precisa mais incluir o `ProductInfoModal.js` na página. Ele será carregado sob demanda. |
|||
|
|||
#### Dica: Bundling & Minification |
|||
|
|||
Embora o carregamento preguiçoso pareça legal no início, ele requer uma chamada adicional ao servidor quando você abre o modal pela primeira vez. |
|||
|
|||
Em vez disso, você pode usar o sistema de [Bundling & Minification](Bundling-Minification.md) para criar um pacote (que é um único arquivo minificado na produção) para todos os arquivos de script usados em uma página: |
|||
|
|||
````html |
|||
<abp-script-bundle> |
|||
<abp-script src="/Pages/Products/ProductInfoModal.js"/> |
|||
<abp-script src="/Pages/Products/Index.js"/> |
|||
</abp-script-bundle> |
|||
```` |
|||
|
|||
Isso é eficiente se o arquivo de script não for grande e for aberto com frequência enquanto os usuários usam a página. |
|||
|
|||
Alternativamente, você pode definir a classe `abp.modals.ProductInfo` no arquivo JavaScript principal da página se o modal for usado apenas e sempre na mesma página. Nesse caso, você não precisa de outro arquivo de script externo. |
|||
@ -0,0 +1,288 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: Menu de Navegação |
|||
|
|||
Toda aplicação possui um menu principal que permite aos usuários navegar para páginas/telas da aplicação. Algumas aplicações podem conter mais de um menu em diferentes seções da interface do usuário. |
|||
|
|||
O ABP Framework é um framework de desenvolvimento de aplicações [modular](../../Module-Development-Basics.md). **Cada módulo pode precisar adicionar itens ao menu**. |
|||
|
|||
Portanto, o ABP Framework **fornece uma infraestrutura de menu** onde: |
|||
|
|||
* A aplicação ou os módulos podem adicionar itens a um menu, sem saber como o menu é renderizado. |
|||
* O [tema](Theming.md) renderiza corretamente o menu. |
|||
|
|||
## Adicionando Itens ao Menu |
|||
|
|||
Para adicionar itens ao menu (ou manipular os itens existentes), você precisa criar uma classe que implemente a interface `IMenuContributor`. |
|||
|
|||
> O [modelo de inicialização da aplicação](../../Startup-Templates/Application.md) já contém uma implementação do `IMenuContributor`. Portanto, você pode adicionar itens dentro dessa classe em vez de criar uma nova. |
|||
|
|||
**Exemplo: Adicionar um item de menu *CRM* com subitens *Clientes* e *Pedidos*** |
|||
|
|||
```csharp |
|||
using System.Threading.Tasks; |
|||
using MyProject.Localization; |
|||
using Volo.Abp.UI.Navigation; |
|||
|
|||
namespace MyProject.Web.Menus |
|||
{ |
|||
public class MyProjectMenuContributor : IMenuContributor |
|||
{ |
|||
public async Task ConfigureMenuAsync(MenuConfigurationContext context) |
|||
{ |
|||
if (context.Menu.Name == StandardMenus.Main) |
|||
{ |
|||
await ConfigureMainMenuAsync(context); |
|||
} |
|||
} |
|||
|
|||
private async Task ConfigureMainMenuAsync(MenuConfigurationContext context) |
|||
{ |
|||
var l = context.GetLocalizer<MyProjectResource>(); |
|||
|
|||
context.Menu.AddItem( |
|||
new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"]) |
|||
.AddItem(new ApplicationMenuItem( |
|||
name: "MyProject.Crm.Customers", |
|||
displayName: l["Menu:Customers"], |
|||
url: "/crm/customers") |
|||
).AddItem(new ApplicationMenuItem( |
|||
name: "MyProject.Crm.Orders", |
|||
displayName: l["Menu:Orders"], |
|||
url: "/crm/orders") |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
* Este exemplo adiciona itens apenas ao menu principal (`StandardMenus.Main`: veja a seção *Menus Padrão* abaixo). |
|||
* Ele obtém um `IStringLocalizer` do `context` para [localizar](../../Localization.md) os nomes de exibição dos itens do menu. |
|||
* Adiciona os Clientes e Pedidos como filhos do menu CRM. |
|||
|
|||
Depois de criar um contribuidor de menu, você precisa adicioná-lo às `AbpNavigationOptions` no método `ConfigureServices` do seu módulo: |
|||
|
|||
````csharp |
|||
Configure<AbpNavigationOptions>(options => |
|||
{ |
|||
options.MenuContributors.Add(new MyProjectMenuContributor()); |
|||
}); |
|||
```` |
|||
|
|||
Este exemplo usa algumas chaves de localização como nomes de exibição, que devem ser definidas no arquivo de localização: |
|||
|
|||
````json |
|||
"Menu:CRM": "CRM", |
|||
"Menu:Orders": "Pedidos", |
|||
"Menu:Customers": "Clientes" |
|||
```` |
|||
|
|||
Consulte o [documento de localização](../../Localization.md) para saber mais sobre a localização. |
|||
|
|||
Quando você executar a aplicação, verá os itens do menu adicionados ao menu principal: |
|||
|
|||
 |
|||
|
|||
> O menu é renderizado pelo tema de interface do usuário atual. Portanto, a aparência do menu principal pode ser completamente diferente com base no seu tema. |
|||
|
|||
Aqui estão algumas observações sobre os contribuidores de menu; |
|||
|
|||
* O ABP Framework chama o método `ConfigureMenuAsync` **sempre que precisar renderizar** o menu. |
|||
* Cada item do menu pode ter **filhos**. Portanto, você pode adicionar itens de menu com **profundidade ilimitada** (no entanto, seu tema de interface do usuário pode não suportar profundidade ilimitada). |
|||
* Apenas os itens de menu folha normalmente têm `url`s. Quando você clica em um menu pai, seu submenu é aberto ou fechado, você não navega para a `url` de um item de menu pai. |
|||
* Se um item de menu não tiver filhos e não tiver uma `url` definida, ele não será renderizado na interface do usuário. Isso simplifica a autorização dos itens do menu: você só autoriza os itens filhos (veja a próxima seção). Se nenhum dos filhos for autorizado, o pai desaparece automaticamente. |
|||
|
|||
### Propriedades do Item do Menu |
|||
|
|||
Existem mais opções de um item do menu (o construtor da classe `ApplicationMenuItem`). Aqui está a lista de todas as opções disponíveis; |
|||
|
|||
* `name` (`string`, obrigatório): O **nome único** do item do menu. |
|||
* `displayName` (`string`, obrigatório): Nome de exibição/texto do item do menu. Você pode [localizar](../../Localization.md) isso como mostrado anteriormente. |
|||
* `url` (`string`): A URL do item do menu. |
|||
* `icon` (`string`): Um nome de ícone. Classes de ícone gratuitas do [Font Awesome](https://fontawesome.com/) são suportadas por padrão. Exemplo: `fa fa-book`. Você pode usar qualquer classe de ícone de fonte CSS, desde que inclua os arquivos CSS necessários em sua aplicação. |
|||
* `order` (`int`): A ordem do item do menu. O valor padrão é `1000`. Os itens são classificados pela ordem de adição, a menos que você especifique um valor de ordem. |
|||
* `customData` (`Dictionary<string, object>`): Um dicionário que permite armazenar objetos personalizados que você pode associar ao item do menu e usá-lo ao renderizar o item do menu. |
|||
* `target` (`string`): Destino do item do menu. Pode ser `null` (padrão), "\_*blank*", "\_*self*", "\_*parent*", "\_*top*" ou um nome de frame para aplicações web. |
|||
* `elementId` (`string`): Pode ser usado para renderizar o elemento com um atributo HTML `id` específico. |
|||
* `cssClass` (`string`): Classes de string adicionais para o item do menu. |
|||
* `groupName` (`string`): Pode ser usado para agrupar itens do menu. |
|||
|
|||
### Autorização |
|||
|
|||
Como visto acima, um contribuidor de menu contribui para o menu dinamicamente. Portanto, você pode executar qualquer lógica personalizada ou obter itens do menu de qualquer fonte. |
|||
|
|||
Um caso de uso é a [autorização](../../Authorization.md). Normalmente, você deseja adicionar itens de menu verificando uma permissão. |
|||
|
|||
**Exemplo: Verificar se o usuário atual possui uma permissão** |
|||
|
|||
````csharp |
|||
if (await context.IsGrantedAsync("NomeDaMinhaPermissao")) |
|||
{ |
|||
//...adicionar itens do menu |
|||
} |
|||
```` |
|||
|
|||
Para a autorização, você pode usar o método de extensão `RequirePermissions` como atalho. Ele também é mais eficiente, o ABP otimiza a verificação de permissão para todos os itens. |
|||
|
|||
````csharp |
|||
context.Menu.AddItem( |
|||
new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"]) |
|||
.AddItem(new ApplicationMenuItem( |
|||
name: "MyProject.Crm.Customers", |
|||
displayName: l["Menu:Customers"], |
|||
url: "/crm/customers") |
|||
.RequirePermissions("MyProject.Crm.Customers") |
|||
).AddItem(new ApplicationMenuItem( |
|||
name: "MyProject.Crm.Orders", |
|||
displayName: l["Menu:Orders"], |
|||
url: "/crm/orders") |
|||
.RequirePermissions("MyProject.Crm.Orders") |
|||
) |
|||
); |
|||
```` |
|||
|
|||
> Você pode usar `context.AuthorizationService` para acessar diretamente o `IAuthorizationService`. |
|||
|
|||
### Resolvendo Dependências |
|||
|
|||
`context.ServiceProvider` pode ser usado para resolver qualquer dependência de serviço. |
|||
|
|||
**Exemplo: Obter um serviço** |
|||
|
|||
````csharp |
|||
var meuServico = context.ServiceProvider.GetRequiredService<IMeuServico>(); |
|||
//...usar o serviço |
|||
```` |
|||
|
|||
> Você não precisa se preocupar em liberar/descartar serviços. O ABP Framework cuida disso. |
|||
|
|||
### O Menu de Administração |
|||
|
|||
Há um item de menu especial no menu que é adicionado pelo ABP Framework: O menu *Administração*. Ele é normalmente usado pelos módulos de administração pré-construídos [application modules](../../Modules/Index.md): |
|||
|
|||
 |
|||
|
|||
Se você deseja adicionar itens de menu sob o item de menu *Administração*, pode usar o método de extensão `context.Menu.GetAdministration()`: |
|||
|
|||
````csharp |
|||
context.Menu.GetAdministration().AddItem(...) |
|||
```` |
|||
|
|||
### Manipulando os Itens do Menu Existente |
|||
|
|||
O ABP Framework executa os contribuidores de menu pela [ordem de dependência do módulo](../../Module-Development-Basics.md). Portanto, você pode manipular os itens do menu nos quais sua aplicação ou módulo (direta ou indiretamente) depende. |
|||
|
|||
**Exemplo: Definir um ícone para o item de menu `Usuários` adicionado pelo [Módulo de Identidade](../../Modules/Identity.md)** |
|||
|
|||
````csharp |
|||
var menuUsuario = context.Menu.FindMenuItem(IdentityMenuNames.Users); |
|||
menuUsuario.Icon = "fa fa-users"; |
|||
```` |
|||
|
|||
> `context.Menu` permite acessar todos os itens do menu que foram adicionados pelos contribuidores de menu anteriores. |
|||
|
|||
### Grupos de Menu |
|||
|
|||
Você pode definir grupos e associar itens de menu a um grupo. |
|||
|
|||
Exemplo: |
|||
|
|||
```csharp |
|||
using System.Threading.Tasks; |
|||
using MyProject.Localization; |
|||
using Volo.Abp.UI.Navigation; |
|||
|
|||
namespace MyProject.Web.Menus |
|||
{ |
|||
public class MyProjectMenuContributor : IMenuContributor |
|||
{ |
|||
public async Task ConfigureMenuAsync(MenuConfigurationContext context) |
|||
{ |
|||
if (context.Menu.Name == StandardMenus.Main) |
|||
{ |
|||
await ConfigureMainMenuAsync(context); |
|||
} |
|||
} |
|||
|
|||
private async Task ConfigureMainMenuAsync(MenuConfigurationContext context) |
|||
{ |
|||
var l = context.GetLocalizer<MyProjectResource>(); |
|||
|
|||
context.Menu.AddGroup( |
|||
new ApplicationMenuGroup( |
|||
name: "Main", |
|||
displayName: l["Main"] |
|||
) |
|||
) |
|||
context.Menu.AddItem( |
|||
new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"], groupName: "Main") |
|||
.AddItem(new ApplicationMenuItem( |
|||
name: "MyProject.Crm.Customers", |
|||
displayName: l["Menu:Customers"], |
|||
url: "/crm/customers") |
|||
).AddItem(new ApplicationMenuItem( |
|||
name: "MyProject.Crm.Orders", |
|||
displayName: l["Menu:Orders"], |
|||
url: "/crm/orders") |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
> O tema de interface do usuário decidirá se renderizará ou não os grupos e, se decidir renderizar, a forma como é renderizado depende do tema. Apenas o tema LeptonX implementa o grupo de menu. |
|||
|
|||
## Menus Padrão |
|||
|
|||
Um menu é um componente **nomeado**. Uma aplicação pode conter mais de um menu com nomes diferentes e exclusivos. Existem dois menus padrão pré-definidos: |
|||
|
|||
* `Main`: O menu principal da aplicação. Contém links para as páginas da aplicação. Definido como uma constante: `Volo.Abp.UI.Navigation.StandardMenus.Main`. |
|||
* `User`: Menu do perfil do usuário. Definido como uma constante: `Volo.Abp.UI.Navigation.StandardMenus.User`. |
|||
|
|||
O menu `Main` já foi abordado acima. O menu `User` está disponível quando um usuário faz login: |
|||
|
|||
 |
|||
|
|||
Você pode adicionar itens ao menu `User` verificando o `context.Menu.Name` como mostrado abaixo: |
|||
|
|||
```csharp |
|||
if (context.Menu.Name == StandardMenus.User) |
|||
{ |
|||
//...adicionar itens |
|||
} |
|||
``` |
|||
|
|||
## IMenuManager |
|||
|
|||
O `IMenuManager` é geralmente usado pelo [tema](Theming.md) de interface do usuário para renderizar os itens do menu na interface do usuário. Portanto, **geralmente você não precisa usar diretamente** o `IMenuManager`. |
|||
|
|||
**Exemplo: Obtendo os itens do menu `Main`** |
|||
|
|||
```csharp |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc.RazorPages; |
|||
using Volo.Abp.UI.Navigation; |
|||
|
|||
namespace MyProject.Web.Pages |
|||
{ |
|||
public class IndexModel : PageModel |
|||
{ |
|||
private readonly IMenuManager _menuManager; |
|||
|
|||
public IndexModel(IMenuManager menuManager) |
|||
{ |
|||
_menuManager = menuManager; |
|||
} |
|||
|
|||
public async Task OnGetAsync() |
|||
{ |
|||
var mainMenu = await _menuManager.GetAsync(StandardMenus.Main); |
|||
|
|||
foreach (var menuItem in mainMenu.Items) |
|||
{ |
|||
//... |
|||
} |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
@ -0,0 +1,160 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI |
|||
|
|||
## Introdução |
|||
|
|||
O ABP Framework oferece uma maneira conveniente e confortável de criar aplicativos da web usando o ASP.NET Core MVC / Razor Pages como framework de interface do usuário. |
|||
|
|||
> O ABP não oferece uma nova/forma personalizada de desenvolvimento de UI. Você pode continuar usando suas habilidades atuais para criar a UI. No entanto, ele oferece muitos recursos para facilitar o desenvolvimento e ter uma base de código mais sustentável. |
|||
|
|||
### MVC vs Razor Pages |
|||
|
|||
O ASP.NET Core oferece dois modelos para o desenvolvimento de UI: |
|||
|
|||
* **[MVC (Model-View-Controller)](https://docs.microsoft.com/en-us/aspnet/core/mvc/)** é a maneira clássica que existe desde a versão 1.0. Este modelo pode ser usado para criar páginas/componentes de UI e APIs HTTP. |
|||
* **[Razor Pages](https://docs.microsoft.com/en-us/aspnet/core/razor-pages/)** foi introduzido com o ASP.NET Core 2.0 como uma nova maneira de criar páginas da web. |
|||
|
|||
**O ABP Framework suporta ambos** os modelos MVC e Razor Pages. No entanto, é sugerido criar as **páginas de UI com a abordagem Razor Pages** e usar o **modelo MVC para construir APIs HTTP**. Portanto, todos os módulos pré-construídos, exemplos e documentação são baseados nas Razor Pages para o desenvolvimento de UI, enquanto você sempre pode aplicar o padrão MVC para criar suas próprias páginas. |
|||
|
|||
### Modularidade |
|||
|
|||
A [modularidade](../../Module-Development-Basics.md) é um dos principais objetivos do ABP Framework. Não é diferente para a UI; É possível desenvolver aplicativos modulares e módulos de aplicativos reutilizáveis com páginas e componentes de UI isolados e reutilizáveis. |
|||
|
|||
O [modelo de inicialização do aplicativo](../../Startup-Templates/Application.md) vem com alguns módulos de aplicativos pré-instalados. Esses módulos têm suas próprias páginas de UI incorporadas em seus próprios pacotes NuGet. Você não vê o código deles em sua solução, mas eles funcionam como esperado em tempo de execução. |
|||
|
|||
## Sistema de Temas |
|||
|
|||
O ABP Framework fornece um completo [sistema de temas](Theming.md) com os seguintes objetivos: |
|||
|
|||
* Módulos de aplicativos reutilizáveis são desenvolvidos de forma **independente de temas**, para que possam funcionar com qualquer tema de UI. |
|||
* O tema de UI é **decidido pelo aplicativo final**. |
|||
* O tema é distribuído por meio de pacotes NuGet/NPM, para que seja **facilmente atualizável**. |
|||
* O aplicativo final pode **personalizar** o tema selecionado. |
|||
|
|||
### Temas Atuais |
|||
|
|||
Atualmente, três temas são **oficialmente fornecidos**: |
|||
|
|||
* O [Tema Básico](Basic-Theme.md) é o tema minimalista com o estilo Bootstrap simples. É **open source e gratuito**. |
|||
* O [Tema Lepton](https://commercial.abp.io/themes) é um tema **comercial** desenvolvido pela equipe principal do ABP e faz parte da licença [ABP Commercial](https://commercial.abp.io/). |
|||
* O [Tema LeptonX](https://x.leptontheme.com/) é um tema que possui escolhas [comerciais](https://docs.abp.io/en/commercial/latest/themes/lepton-x/mvc) e [lite](../../Themes/LeptonXLite/AspNetCore.md). |
|||
|
|||
Também existem alguns temas desenvolvidos pela comunidade para o ABP Framework (você pode pesquisar na web). |
|||
|
|||
### Bibliotecas Base |
|||
|
|||
Existem um conjunto de bibliotecas JavaScript/CSS padrão que são pré-instaladas e suportadas por todos os temas: |
|||
|
|||
- [Twitter Bootstrap](https://getbootstrap.com/) como o framework HTML/CSS fundamental. |
|||
- [JQuery](https://jquery.com/) para manipulação do DOM. |
|||
- [DataTables.Net](https://datatables.net/) para grades de dados. |
|||
- [JQuery Validation](https://jqueryvalidation.org/) para validação do lado do cliente e [unobtrusive](https://github.com/aspnet/jquery-validation-unobtrusive) validation |
|||
- [FontAwesome](https://fontawesome.com/) como a biblioteca fundamental de fontes CSS. |
|||
- [SweetAlert](https://sweetalert.js.org/) para mostrar mensagens de alerta e caixas de diálogo de confirmação. |
|||
- [Toastr](https://github.com/CodeSeven/toastr) para mostrar notificações de toast. |
|||
- [Lodash](https://lodash.com/) como uma biblioteca de utilitários. |
|||
- [Luxon](https://moment.github.io/luxon/) para operações de data/hora. |
|||
- [JQuery Form](https://github.com/jquery-form/form) para formulários AJAX. |
|||
- [bootstrap-datepicker](https://github.com/uxsolutions/bootstrap-datepicker) para mostrar seletores de data. |
|||
- [Select2](https://select2.org/) para melhores caixas de seleção/combo. |
|||
- [Timeago](http://timeago.yarp.com/) para mostrar carimbos de data/hora fuzzy atualizados automaticamente. |
|||
- [malihu-custom-scrollbar-plugin](https://github.com/malihu/malihu-custom-scrollbar-plugin) para barras de rolagem personalizadas. |
|||
|
|||
Você pode usar essas bibliotecas diretamente em seus aplicativos, sem precisar importar manualmente sua página. |
|||
|
|||
### Layouts |
|||
|
|||
Os temas fornecem os layouts padrão. Portanto, você tem layouts responsivos com os recursos padrão já implementados. A captura de tela abaixo foi tirada do Layout do Aplicativo do [Tema Básico](Basic-Theme.md): |
|||
|
|||
 |
|||
|
|||
Consulte o documento [Theming](Theming.md) para obter mais opções de layout e outros detalhes. |
|||
|
|||
### Partes do Layout |
|||
|
|||
Um layout típico consiste em várias partes. O sistema de [temas](Theming.md) fornece [menus](Navigation-Menu.md), [toolbars](Toolbars.md), [hooks de layout](Layout-Hooks.md) e mais para controlar dinamicamente o layout pelo seu aplicativo e pelos módulos que você está usando. |
|||
|
|||
## Recursos |
|||
|
|||
Esta seção destaca alguns dos recursos fornecidos pelo ABP Framework para a UI do ASP.NET Core MVC / Razor Pages. |
|||
|
|||
### Proxies de Cliente de API JavaScript Dinâmico |
|||
|
|||
O sistema de Proxies de Cliente de API JavaScript Dinâmico permite que você consuma suas APIs HTTP do lado do servidor a partir do seu código de cliente JavaScript, assim como chamar funções locais. |
|||
|
|||
**Exemplo: Obter uma lista de autores do servidor** |
|||
|
|||
````js |
|||
acme.bookStore.authors.author.getList({ |
|||
maxResultCount: 10 |
|||
}).then(function(result){ |
|||
console.log(result.items); |
|||
}); |
|||
```` |
|||
|
|||
`acme.bookStore.authors.author.getList` é uma função gerada automaticamente que faz internamente uma chamada AJAX para o servidor. |
|||
|
|||
Consulte o documento [Proxies de Cliente de API JavaScript Dinâmico](Dynamic-JavaScript-Proxies.md) para mais informações. |
|||
|
|||
### Tag Helpers do Bootstrap |
|||
|
|||
O ABP torna mais fácil e seguro escrever HTML do Bootstrap. |
|||
|
|||
**Exemplo: Renderizar um modal do Bootstrap** |
|||
|
|||
````html |
|||
<abp-modal> |
|||
<abp-modal-header title="Título do Modal" /> |
|||
<abp-modal-body> |
|||
Uau, você está lendo este texto em um modal! |
|||
</abp-modal-body> |
|||
<abp-modal-footer buttons="@(AbpModalButtons.Save|AbpModalButtons.Close)"></abp-modal-footer> |
|||
</abp-modal> |
|||
```` |
|||
|
|||
Consulte o documento [Tag Helpers](Tag-Helpers/Index.md) para mais informações. |
|||
|
|||
### Formulários e Validação |
|||
|
|||
O ABP fornece os tag helpers `abp-dynamic-form` e `abp-input` para simplificar drasticamente a criação de um formulário totalmente funcional que automatiza a localização, validação e envio AJAX. |
|||
|
|||
**Exemplo: Use `abp-dynamic-form` para criar um formulário completo com base em um modelo** |
|||
|
|||
````html |
|||
<abp-dynamic-form abp-model="Movie" submit-button="true" /> |
|||
```` |
|||
|
|||
Consulte o documento [Formulários e Validação](Forms-Validation.md) para obter mais detalhes. |
|||
|
|||
### Agrupamento e Minificação / Bibliotecas do Lado do Cliente |
|||
|
|||
O ABP fornece um sistema de Agrupamento e Minificação flexível e modular para criar pacotes e minificar arquivos de estilo/script em tempo de execução. |
|||
|
|||
````html |
|||
<abp-style-bundle> |
|||
<abp-style src="/libs/bootstrap/css/bootstrap.css" /> |
|||
<abp-style src="/libs/font-awesome/css/font-awesome.css" /> |
|||
<abp-style src="/libs/toastr/toastr.css" /> |
|||
<abp-style src="/styles/my-global-style.css" /> |
|||
</abp-style-bundle> |
|||
```` |
|||
|
|||
Além disso, o sistema de Gerenciamento de Pacotes do Lado do Cliente oferece uma maneira modular e consistente de gerenciar dependências de bibliotecas de terceiros. |
|||
|
|||
Consulte os documentos [Agrupamento e Minificação](Bundling-Minification.md) e [Gerenciamento de Pacotes do Lado do Cliente](Client-Side-Package-Management.md). |
|||
|
|||
### APIs JavaScript |
|||
|
|||
As [APIs JavaScript](JavaScript-API/Index.md) fornecem abstrações sólidas para a localização, configurações, permissões, recursos... etc. do lado do servidor. Elas também fornecem uma maneira simples de mostrar mensagens e **notificações** ao usuário. |
|||
|
|||
### Modais, Alertas, Widgets e Mais |
|||
|
|||
O ABP Framework fornece muitas soluções integradas para requisitos comuns de aplicativos; |
|||
|
|||
* O [Sistema de Widgets](Widgets.md) pode ser usado para criar widgets reutilizáveis e criar painéis de controle. |
|||
* Os [Alertas de Página](Page-Alerts.md) facilitam a exibição de alertas ao usuário. |
|||
* O [Gerenciador de Modais](Modals.md) fornece uma maneira simples de construir e usar modais. |
|||
* A integração com [Data Tables](Data-Tables.md) facilita a criação de grades de dados. |
|||
|
|||
## Personalização |
|||
|
|||
Existem muitas maneiras de personalizar o tema e as UIs dos módulos pré-construídos. Você pode substituir componentes, páginas, recursos estáticos, pacotes e muito mais. Consulte o [Guia de Personalização da Interface do Usuário](Customization-User-Interface.md) para mais informações. |
|||
@ -0,0 +1,84 @@ |
|||
# ASP.NET Core MVC / Razor Pages: Alertas de Página |
|||
|
|||
É comum mostrar alertas de erro, aviso ou informação para informar o usuário. Um exemplo de alerta de *Interrupção de Serviço* é mostrado abaixo: |
|||
|
|||
 |
|||
|
|||
## Uso Básico |
|||
|
|||
Se você herda diretamente ou indiretamente de `AbpPageModel`, você pode usar a propriedade `Alerts` para adicionar alertas que serão renderizados após a conclusão da solicitação. |
|||
|
|||
**Exemplo: Mostrar um alerta de aviso** |
|||
|
|||
```csharp |
|||
namespace MyProject.Web.Pages |
|||
{ |
|||
public class IndexModel : MyProjectPageModel //ou herde de AbpPageModel |
|||
{ |
|||
public void OnGet() |
|||
{ |
|||
Alerts.Warning( |
|||
text: "Teremos uma interrupção de serviço entre 02:00 e 04:00 em 23 de outubro de 2023!", |
|||
title: "Interrupção de Serviço" |
|||
); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
Este uso renderiza um alerta que foi mostrado acima. Se você precisar localizar as mensagens, você sempre pode usar o sistema padrão de [localização](../../Localization.md). |
|||
|
|||
### Exceções / Estados Inválidos do Modelo |
|||
|
|||
É comum mostrar alertas quando você manipula manualmente exceções (com declarações try/catch) ou deseja lidar com o caso `!ModelState.IsValid` e avisar o usuário. Por exemplo, o Módulo de Conta mostra um aviso se o usuário inserir um nome de usuário ou senha incorretos: |
|||
|
|||
 |
|||
|
|||
> Observe que geralmente você não precisa manipular exceções manualmente, pois o ABP Framework fornece um sistema automático de [manipulação de exceções](../../Exception-Handling.md). |
|||
|
|||
### Tipos de Alerta |
|||
|
|||
`Warning` é usado para mostrar um alerta de aviso. Outros métodos comuns são `Info`, `Danger` e `Success`. |
|||
|
|||
Além dos métodos padrão, você pode usar o método `Alerts.Add` passando um `enum` `AlertType` com um desses valores: `Default`, `Primary`, `Secondary`, `Success`, `Danger`, `Warning`, `Info`, `Light`, `Dark`. |
|||
|
|||
### Dispensável |
|||
|
|||
Todos os métodos de alerta recebem um parâmetro opcional `dismissible`. O valor padrão é `true`, o que torna a caixa de alerta dispensável. Defina-o como `false` para criar uma caixa de alerta fixa. |
|||
|
|||
## IAlertManager |
|||
|
|||
Se você precisar adicionar mensagens de alerta de outra parte do seu código, você pode injetar o serviço `IAlertManager` e usar sua lista `Alerts`. |
|||
|
|||
**Exemplo: Injetar o `IAlertManager`** |
|||
|
|||
```csharp |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Alerts; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace MyProject.Web.Pages |
|||
{ |
|||
public class MyService : ITransientDependency |
|||
{ |
|||
private readonly IAlertManager _alertManager; |
|||
|
|||
public MyService(IAlertManager alertManager) |
|||
{ |
|||
_alertManager = alertManager; |
|||
} |
|||
|
|||
public void Test() |
|||
{ |
|||
_alertManager.Alerts.Add(AlertType.Danger, "Mensagem de teste!"); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Notas |
|||
|
|||
### Requisições AJAX |
|||
|
|||
O sistema de Alerta de Página foi projetado para ser usado em uma solicitação regular de página completa. Não é para requisições AJAX/partial. Os alertas são renderizados no layout da página, portanto, é necessário atualizar a página inteira. |
|||
|
|||
Para requisições AJAX, é mais adequado lançar exceções (por exemplo, `UserFriendlyException`). Consulte o documento de [manipulação de exceções](../../Exception-Handling.md). |
|||
@ -0,0 +1,62 @@ |
|||
# ASP.NET Core MVC / Razor Pages: Cabeçalho da Página |
|||
|
|||
O serviço `IPageLayout` pode ser usado para definir o título da página, o item de menu selecionado e os itens do breadcrumb para uma página. É responsabilidade do [tema](Theming.md) renderar esses elementos na página. |
|||
|
|||
## IPageLayout |
|||
|
|||
O `IPageLayout` pode ser injetado em qualquer página/view para definir as propriedades do cabeçalho da página. |
|||
|
|||
### Título da Página |
|||
|
|||
O título da página pode ser definido da seguinte forma: |
|||
|
|||
```csharp |
|||
@inject IPageLayout PageLayout |
|||
@{ |
|||
PageLayout.Content.Title = "Lista de Livros"; |
|||
} |
|||
``` |
|||
|
|||
* O título da página é definido na tag HTML `title` (além do [nome da marca/aplicativo](Branding.md)). |
|||
* O tema pode renderizar o título da página antes do conteúdo da página (ainda não implementado pelo Tema Básico). |
|||
|
|||
### Breadcrumb |
|||
|
|||
> **O [Tema Básico](Basic-Theme.md) atualmente não implementa o breadcrumb.** |
|||
> |
|||
> O [Tema LeptonX Lite](../../Themes/LeptonXLite/AspNetCore.md) suporta o breadcrumb. |
|||
|
|||
Itens do breadcrumb podem ser adicionados ao `PageLayout.Content.BreadCrumb`. |
|||
|
|||
**Exemplo: Adicionar Gerenciamento de Idioma aos itens do breadcrumb.** |
|||
|
|||
``` |
|||
PageLayout.Content.BreadCrumb.Add("Gerenciamento de Idioma"); |
|||
``` |
|||
|
|||
O tema então renderiza o breadcrumb. Um exemplo do resultado renderizado pode ser: |
|||
|
|||
 |
|||
|
|||
* O ícone Home é renderizado por padrão. Defina `PageLayout.Content.BreadCrumb.ShowHome` como `false` para ocultá-lo. |
|||
* O nome da página atual (obtido do `PageLayout.Content.Title`) é adicionado por padrão como o último item. Defina `PageLayout.Content.BreadCrumb.ShowCurrent` como `false` para ocultá-lo. |
|||
|
|||
Qualquer item que você adicionar é inserido entre o Home e os itens da página atual. Você pode adicionar quantos itens forem necessários. O método `BreadCrumb.Add(...)` recebe três parâmetros: |
|||
|
|||
* `text`: O texto a ser exibido para o item do breadcrumb. |
|||
* `url` (opcional): Uma URL para navegar, se o usuário clicar no item do breadcrumb. |
|||
* `icon` (opcional): Uma classe de ícone (como `fas fa-user-tie` para Font-Awesome) para exibir junto com o `text`. |
|||
|
|||
### O Item de Menu Selecionado |
|||
|
|||
> **O [Tema Básico](Basic-Theme.md) atualmente não implementa o item de menu selecionado, pois não é aplicável ao menu superior, que é a única opção para o Tema Básico no momento.** |
|||
> |
|||
> O [Tema LeptonX Lite](../../Themes/LeptonXLite/AspNetCore.md) suporta o item de menu selecionado. |
|||
|
|||
Você pode definir o nome do item de menu relacionado a esta página: |
|||
|
|||
```csharp |
|||
PageLayout.Content.MenuItemName = "BookStore.Books"; |
|||
``` |
|||
|
|||
O nome do item de menu deve corresponder a um nome de item de menu único definido usando o sistema de [Navegação / Menu](Navigation-Menu.md). Nesse caso, espera-se que o tema torne o item de menu "ativo" no menu principal. |
|||
@ -0,0 +1,162 @@ |
|||
# Extensões da Barra de Ferramentas da Página para a Interface do Usuário ASP.NET Core |
|||
|
|||
O sistema de barra de ferramentas da página permite adicionar componentes à barra de ferramentas de qualquer página. A barra de ferramentas da página é a área à direita do cabeçalho de uma página. Um botão ("Importar usuários do Excel") foi adicionado à página de gerenciamento de usuários abaixo: |
|||
|
|||
 |
|||
|
|||
Você pode adicionar qualquer tipo de componente de visualização à barra de ferramentas da página ou modificar os itens existentes. |
|||
|
|||
## Como Configurar |
|||
|
|||
Neste exemplo, adicionaremos um botão "Importar usuários do Excel" e executaremos um código JavaScript para a página de gerenciamento de usuários do [Módulo de Identidade](../../Modules/Identity.md). |
|||
|
|||
### Adicionar um Novo Botão à Página de Gerenciamento de Usuários |
|||
|
|||
Escreva o seguinte código dentro do método `ConfigureServices` da classe do seu módulo web: |
|||
|
|||
````csharp |
|||
Configure<AbpPageToolbarOptions>(options => |
|||
{ |
|||
options.Configure<Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel>(toolbar => |
|||
{ |
|||
toolbar.AddButton( |
|||
LocalizableString.Create<MyProjectNameResource>("ImportFromExcel"), |
|||
icon: "file-import", |
|||
id: "ImportUsersFromExcel", |
|||
type: AbpButtonType.Secondary |
|||
); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
`AddButton` é um atalho para simplesmente adicionar um componente de botão. Observe que você precisa adicionar a chave `ImportFromExcel` ao seu dicionário de localização (arquivo json) para localizar o texto. |
|||
|
|||
Quando você executar a aplicação, verá o botão adicionado ao lado da lista de botões atual. Existem outros parâmetros do método `AddButton` (por exemplo, use `order` para definir a ordem do componente de botão em relação aos outros componentes). |
|||
|
|||
### Criar um Arquivo JavaScript |
|||
|
|||
Agora, podemos ir para o lado do cliente para lidar com o evento de clique do novo botão. Primeiro, adicione um novo arquivo JavaScript à sua solução. Nós adicionamos dentro da pasta `/Pages/Identity/Users` do projeto `.Web`: |
|||
|
|||
 |
|||
|
|||
Aqui está o conteúdo deste arquivo JavaScript: |
|||
|
|||
````js |
|||
$(function () { |
|||
$('#ImportUsersFromExcel').click(function (e) { |
|||
e.preventDefault(); |
|||
alert('TODO: importar usuários do Excel'); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
No evento `click`, você pode fazer qualquer coisa que precise fazer. |
|||
|
|||
### Adicionar o Arquivo à Página de Gerenciamento de Usuários |
|||
|
|||
Em seguida, você precisa adicionar este arquivo JavaScript à página de gerenciamento de usuários. Você pode aproveitar o poder do sistema de [Agrupamento e Minificação](Bundling-Minification.md). |
|||
|
|||
Escreva o seguinte código dentro do método `ConfigureServices` da classe do seu módulo: |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options.ScriptBundles.Configure( |
|||
typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName, |
|||
bundleConfiguration => |
|||
{ |
|||
bundleConfiguration.AddFiles( |
|||
"/Pages/Identity/Users/my-user-extensions.js" |
|||
); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
Essa configuração adiciona `my-user-extensions.js` à página de gerenciamento de usuários do Módulo de Identidade. `typeof(Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel).FullName` é o nome do pacote na página de gerenciamento de usuários. Essa é uma convenção comum usada para todos os módulos comerciais do ABP. |
|||
|
|||
## Casos de Uso Avançados |
|||
|
|||
Embora você normalmente queira adicionar uma ação de botão à barra de ferramentas da página, é possível adicionar qualquer tipo de componente. |
|||
|
|||
### Adicionar um Componente de Visualização à Barra de Ferramentas da Página |
|||
|
|||
Primeiro, crie um novo componente de visualização em seu projeto: |
|||
|
|||
 |
|||
|
|||
Para este exemplo, criamos um componente de visualização `MyToolbarItem` na pasta `/Pages/Identity/Users/MyToolbarItem`. |
|||
|
|||
Conteúdo de `MyToolbarItemViewComponent.cs`: |
|||
|
|||
````csharp |
|||
public class MyToolbarItemViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View("~/Pages/Identity/Users/MyToolbarItem/Default.cshtml"); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Conteúdo de `Default.cshtml`: |
|||
|
|||
````xml |
|||
<span> |
|||
<button type="button" class="btn btn-dark">CLIQUE AQUI</button> |
|||
</span> |
|||
```` |
|||
|
|||
* O arquivo `.cshtml` pode conter qualquer tipo de componente(s). É um componente de visualização típico. |
|||
* `MyToolbarItemViewComponent` pode injetar e usar qualquer serviço, se necessário. |
|||
|
|||
Em seguida, você pode adicionar o `MyToolbarItemViewComponent` à página de gerenciamento de usuários: |
|||
|
|||
````csharp |
|||
Configure<AbpPageToolbarOptions>(options => |
|||
{ |
|||
options.Configure<Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel>( |
|||
toolbar => |
|||
{ |
|||
toolbar.AddComponent<MyToolbarItemViewComponent>(); |
|||
} |
|||
); |
|||
}); |
|||
```` |
|||
|
|||
* Se o seu componente aceitar argumentos (no método `Invoke`/`InvokeAsync`), você pode passá-los para o método `AddComponent` como um objeto anônimo. |
|||
|
|||
#### Permissões |
|||
|
|||
Se o seu botão/componente deve estar disponível com base em uma [permissão/política](../../Authorization.md), você pode passar o nome da permissão/política como parâmetro `requiredPolicyName` para os métodos `AddButton` e `AddComponent`. |
|||
|
|||
### Adicionar um Contribuidor da Barra de Ferramentas da Página |
|||
|
|||
Se você realizar uma lógica personalizada avançada ao adicionar um item à barra de ferramentas de uma página, pode criar uma classe que implementa a interface `IPageToolbarContributor` ou herda da classe `PageToolbarContributor`: |
|||
|
|||
````csharp |
|||
public class MyToolbarContributor : PageToolbarContributor |
|||
{ |
|||
public override Task ContributeAsync(PageToolbarContributionContext context) |
|||
{ |
|||
context.Items.Insert(0, new PageToolbarItem(typeof(MyToolbarItemViewComponent))); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* Você pode usar `context.ServiceProvider` para resolver dependências, se necessário. |
|||
|
|||
Em seguida, adicione sua classe à lista `Contributors`: |
|||
|
|||
````csharp |
|||
Configure<AbpPageToolbarOptions>(options => |
|||
{ |
|||
options.Configure<Volo.Abp.Identity.Web.Pages.Identity.Users.IndexModel>( |
|||
toolbar => |
|||
{ |
|||
toolbar.Contributors.Add(new MyToolbarContributor()); |
|||
} |
|||
); |
|||
}); |
|||
```` |
|||
@ -0,0 +1,99 @@ |
|||
# Cabeçalhos de Segurança |
|||
|
|||
O ABP Framework permite que você adicione cabeçalhos de segurança frequentemente usados em sua aplicação. Os seguintes cabeçalhos de segurança serão adicionados como cabeçalhos de resposta à sua aplicação se você usar o middleware `UseAbpSecurityHeaders`: |
|||
|
|||
* `X-Content-Type-Options`: Informa ao navegador para não tentar adivinhar qual pode ser o tipo MIME de um recurso e apenas aceitar o tipo MIME retornado pelo servidor. |
|||
* `X-XSS-Protection`: Esta é uma funcionalidade do Internet Explorer, Chrome e Safari que impede o carregamento de páginas quando detectam ataques de cross-site scripting (XSS) refletidos. |
|||
* `X-Frame-Options`: Este cabeçalho pode ser usado para indicar se um navegador deve ou não ser permitido a renderizar uma página em uma tag `<iframe>`. Ao especificar o valor desse cabeçalho como *SAMEORIGIN*, você pode fazer com que a página seja exibida em um frame na mesma origem da própria página. |
|||
* `Content-Security-Policy`: Este cabeçalho de resposta permite restringir quais recursos (como JavaScript, CSS, imagens, manifestos, etc.) podem ser carregados e os URLs de onde eles podem ser carregados. Esse cabeçalho de segurança só será adicionado se você configurar a classe `AbpSecurityHeadersOptions` e ativá-lo. |
|||
|
|||
## Configuração |
|||
|
|||
### AbpSecurityHeadersOptions |
|||
|
|||
`AbpSecurityHeadersOptions` é a classe principal para habilitar o cabeçalho `Content-Security-Policy`, definir seu valor e adicionar outros cabeçalhos de segurança que você deseja adicionar à sua aplicação. |
|||
|
|||
**Exemplo:** |
|||
|
|||
```csharp |
|||
Configure<AbpSecurityHeadersOptions>(options => |
|||
{ |
|||
options.UseContentSecurityPolicyHeader = true; //false por padrão |
|||
options.ContentSecurityPolicyValue = "object-src 'none'; form-action 'self'; frame-ancestors 'none'"; //valor padrão |
|||
|
|||
//adicionando cabeçalhos de segurança adicionais |
|||
options.Headers["Referrer-Policy"] = "no-referrer"; |
|||
}); |
|||
``` |
|||
|
|||
> Se o cabeçalho for o mesmo, os cabeçalhos de segurança adicionais que você definiu têm precedência sobre os cabeçalhos de segurança padrão. Em outras palavras, eles substituem os valores padrão dos cabeçalhos de segurança. |
|||
|
|||
## Middleware de Cabeçalhos de Segurança |
|||
|
|||
O middleware de Cabeçalhos de Segurança é um middleware da pipeline de solicitação do ASP.NET Core que adiciona cabeçalhos de segurança predefinidos à sua aplicação, incluindo `X-Content-Type-Options`, `X-XSS-Protection` e `X-Frame-Options`. Além disso, esse middleware também inclui esses cabeçalhos de segurança exclusivos em sua aplicação se você configurar a classe `AbpSecurityHeadersOptions` conforme mencionado acima. |
|||
|
|||
**Exemplo:** |
|||
|
|||
```csharp |
|||
app.UseAbpSecurityHeaders(); |
|||
``` |
|||
|
|||
> Você pode adicionar esse middleware após `app.UseRouting()` no método `OnApplicationInitialization` da classe do seu módulo para registrá-lo na pipeline de solicitação. Esse middleware já está configurado nos [ABP Commercial Startup Templates](https://docs.abp.io/en/commercial/latest/startup-templates/index), portanto, você não precisa adicioná-lo manualmente se estiver usando um desses modelos de inicialização. |
|||
|
|||
Depois de registrar o middleware `UseAbpSecurityHeaders` na pipeline de solicitação, os cabeçalhos de segurança definidos serão exibidos nos cabeçalhos de resposta, como na figura abaixo: |
|||
|
|||
 |
|||
|
|||
## Nonce de Script da Política de Segurança de Conteúdo |
|||
|
|||
O Abp Framework fornece uma propriedade para adicionar um valor de nonce dinâmico ao cabeçalho Content-Security-Policy. Com esse recurso, ele adiciona automaticamente um valor de nonce dinâmico ao lado do cabeçalho. E com a ajuda do helper de tag de script, ele adiciona esse valor de [`nonce de script`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) às tags de script em suas páginas (o `ScriptNonceTagHelper` no namespace `Volo.Abp.AspNetCore.Mvc.UI.Bundling` deve ser anexado como um taghelper). |
|||
> Se você precisar adicionar manualmente o nonce de script, pode usar 'Html.GetScriptNonce()' para adicionar o valor de nonce ou 'Html.GetScriptNonceAttribute()' para adicionar o valor do atributo nonce. |
|||
|
|||
Esse recurso está desabilitado por padrão. Você pode ativá-lo definindo a propriedade `UseContentSecurityPolicyScriptNonce` da classe `AbpSecurityHeadersOptions` como `true`. |
|||
|
|||
### Ignorar Nonce de Script |
|||
|
|||
Você pode ignorar o nonce de script para algumas páginas ou alguns seletores. Você pode usar as propriedades `IgnoredScriptNoncePaths` e `IgnoredScriptNonceSelectors` da classe `AbpSecurityHeadersOptions`. |
|||
|
|||
**Exemplo:** |
|||
|
|||
```csharp |
|||
Configure<AbpSecurityHeadersOptions>(options => |
|||
{ |
|||
//adicionando nonce de script-src |
|||
options.UseContentSecurityPolicyScriptNonce = true; //false por padrão |
|||
|
|||
//ignorar a origem do nonce de script para esses caminhos |
|||
options.IgnoredScriptNoncePaths.Add("/minha-pagina"); |
|||
|
|||
//ignorar o nonce de script por Elsa Workflows e outros seletores |
|||
options.IgnoredScriptNonceSelectors.Add(context => |
|||
{ |
|||
var endpoint = context.GetEndpoint(); |
|||
return Task.FromResult(endpoint?.Metadata.GetMetadata<PageRouteMetadata>()?.RouteTemplate == "/{SUA_PAGINA_PRINCIPAL}"); |
|||
}); |
|||
}); |
|||
``` |
|||
|
|||
### Ignorar Cabeçalhos de Segurança do Abp |
|||
|
|||
Você pode ignorar os Cabeçalhos de Segurança do Abp para algumas ações ou páginas. Você pode usar o atributo `IgnoreAbpSecurityHeaderAttribute` para isso. |
|||
|
|||
**Exemplo:** |
|||
|
|||
```csharp |
|||
@using Volo.Abp.AspNetCore.Security |
|||
@attribute [IgnoreAbpSecurityHeaderAttribute] |
|||
``` |
|||
|
|||
**Exemplo:** |
|||
|
|||
```csharp |
|||
[IgnoreAbpSecurityHeaderAttribute] |
|||
public class IndexModel : AbpPageModel |
|||
{ |
|||
public void OnGet() |
|||
{ |
|||
} |
|||
} |
|||
``` |
|||
@ -0,0 +1,157 @@ |
|||
# Proxies de Cliente Estático da API JavaScript |
|||
|
|||
É comum consumir suas APIs HTTP a partir do seu código JavaScript. Para fazer isso, normalmente você lida com chamadas AJAX de baixo nível, como $.ajax, ou melhor [abp.ajax](JavaScript-API/Ajax.md). O ABP Framework fornece **uma maneira melhor** de chamar suas APIs HTTP a partir do seu código JavaScript: Proxies de Cliente da API JavaScript! |
|||
|
|||
## Proxies de Cliente JavaScript Estáticos vs Dinâmicos |
|||
|
|||
O ABP fornece **dois tipos** de sistema de geração de proxy de cliente. Este documento explica os **proxies de cliente estáticos**, que geram código do lado do cliente durante o desenvolvimento. Você também pode ver a documentação [Proxies de Cliente JavaScript Dinâmicos da API](Dynamic-JavaScript-Proxies.md) para aprender como usar proxies gerados em tempo de execução. |
|||
|
|||
A geração de proxy de cliente em tempo de desenvolvimento (estático) tem uma **ligeira vantagem de desempenho**, pois não precisa obter a definição da API HTTP em tempo de execução. No entanto, você deve **regenerar** o código do proxy do cliente sempre que alterar a definição do ponto de extremidade da API. Por outro lado, os proxies de cliente dinâmicos são gerados em tempo de execução e oferecem uma **experiência de desenvolvimento mais fácil**. |
|||
|
|||
## Um Exemplo Rápido |
|||
|
|||
### O Serviço de Aplicativo |
|||
|
|||
Suponha que você tenha um serviço de aplicativo definido como mostrado abaixo: |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace Acme.BookStore.Authors |
|||
{ |
|||
public interface IAuthorAppService : IApplicationService |
|||
{ |
|||
Task<AuthorDto> GetAsync(Guid id); |
|||
|
|||
Task<PagedResultDto<AuthorDto>> GetListAsync(GetAuthorListDto input); |
|||
|
|||
Task<AuthorDto> CreateAsync(CreateAuthorDto input); |
|||
|
|||
Task UpdateAsync(Guid id, UpdateAuthorDto input); |
|||
|
|||
Task DeleteAsync(Guid id); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
> Você pode seguir o [tutorial de desenvolvimento de aplicativos da web](../../Tutorials/Part-1.md) para aprender como criar [serviços de aplicativos](../../Application-Services.md), expô-los como [APIs HTTP](../../API/Auto-API-Controllers.md) e consumir do código JavaScript como um exemplo completo. |
|||
|
|||
### Gerando o Código JavaScript |
|||
|
|||
O lado do servidor deve estar em execução ao gerar o código do proxy do cliente. Portanto, execute primeiro a aplicação que hospeda suas APIs HTTP (pode ser a aplicação Web ou a aplicação HttpApi.Host, dependendo da estrutura da sua solução). |
|||
|
|||
Abra um terminal de linha de comando na pasta raiz do seu projeto da web (`.csproj`) e digite o seguinte comando: |
|||
|
|||
````bash |
|||
abp generate-proxy -t js -u https://localhost:53929/ |
|||
```` |
|||
|
|||
> Se você ainda não instalou, deve instalar o [ABP CLI](../../CLI.md). Altere a URL de exemplo para a URL raiz da sua aplicação. |
|||
|
|||
Este comando deve gerar os seguintes arquivos na pasta `ClientProxies`: |
|||
|
|||
 |
|||
|
|||
`app-proxy.js` é o arquivo de proxy gerado neste exemplo. Aqui, um exemplo de função de proxy neste arquivo: |
|||
|
|||
````js |
|||
acme.bookStore.authors.author.get = function(id, ajaxParams) { |
|||
return abp.ajax($.extend(true, { |
|||
url: abp.appPath + 'api/app/author/' + id + '', |
|||
type: 'GET' |
|||
}, ajaxParams)); |
|||
}; |
|||
```` |
|||
|
|||
> O comando `generate-proxy` gera proxies apenas para as APIs que você definiu em sua aplicação (assume `app` como o nome do módulo). Se você está desenvolvendo uma aplicação modular, pode especificar o parâmetro `-m` (ou `--module`) para especificar o módulo para o qual deseja gerar proxies. Consulte a seção *generate-proxy* na documentação do [ABP CLI](../CLI.md) para outras opções. |
|||
|
|||
### Usando as Funções de Proxy |
|||
|
|||
Para usar as funções de proxy, primeiro importe o arquivo `app-proxy.js` para a sua página: |
|||
|
|||
````html |
|||
<abp-script src="/client-proxies/app-proxy.js"/> |
|||
```` |
|||
|
|||
> Usamos o [abp-script tag helper](Bundling-Minification.md) neste exemplo. Você pode usar a tag `script` padrão, mas o `abp-script` é a maneira recomendada de importar arquivos JavaScript para suas páginas. |
|||
|
|||
Agora, você pode chamar qualquer um dos métodos do serviço de aplicativo a partir do seu código JavaScript, assim como chamar uma função JavaScript. A função JavaScript tem o mesmo **nome**, **parâmetros** e **valor de retorno** do método C#. |
|||
|
|||
**Exemplo: Obter um único autor** |
|||
|
|||
````js |
|||
acme.bookStore.authors.author |
|||
.get("7245a066-5457-4941-8aa7-3004778775f0") //Obtenha o id de algum lugar! |
|||
.then(function(result){ |
|||
console.log(result); |
|||
}); |
|||
```` |
|||
|
|||
**Exemplo: Obter a lista de autores** |
|||
|
|||
````js |
|||
acme.bookStore.authors.author.getList({ |
|||
maxResultCount: 10 |
|||
}).then(function(result){ |
|||
console.log(result.items); |
|||
}); |
|||
```` |
|||
|
|||
**Exemplo: Excluir um autor** |
|||
|
|||
```js |
|||
acme.bookStore.authors.author |
|||
.delete('7245a066-5457-4941-8aa7-3004778775f0') //Obtenha o id de algum lugar! |
|||
.then(function() { |
|||
abp.notify.info('Excluído com sucesso!'); |
|||
}); |
|||
``` |
|||
|
|||
## Desabilitando Proxies JavaScript Dinâmicos |
|||
|
|||
Quando você cria um aplicativo ou módulo, a abordagem de [geração dinâmica de proxy de cliente](Dynamic-JavaScript-Proxies.md) é usada por padrão. Se você deseja usar os proxies de cliente gerados estaticamente para o seu aplicativo, você deve desabilitá-lo explicitamente para o seu aplicativo ou módulo no método `ConfigureServices` da sua [classe de módulo](../../Module-Development-Basics.md), como no exemplo a seguir: |
|||
|
|||
````csharp |
|||
Configure<DynamicJavaScriptProxyOptions>(options => |
|||
{ |
|||
options.DisableModule("app"); |
|||
}); |
|||
```` |
|||
|
|||
`app` representa o aplicativo principal neste exemplo, o que funciona se você estiver criando um aplicativo. Se você estiver desenvolvendo um módulo de aplicativo, use o nome do seu módulo. |
|||
|
|||
## Detalhes do AJAX |
|||
|
|||
As funções de proxy do cliente JavaScript usam o [abp.ajax](JavaScript-API/Ajax.md) por baixo dos panos. Portanto, você tem os mesmos benefícios, como **tratamento automático de erros**. Além disso, você pode controlar totalmente a chamada AJAX fornecendo as opções. |
|||
|
|||
### O Valor de Retorno |
|||
|
|||
Cada função retorna um [objeto Deferred](https://api.jquery.com/category/deferred-object/). Isso significa que você pode encadear com `then` para obter o resultado, `catch` para lidar com o erro, `always` para executar uma ação assim que a operação for concluída (sucesso ou falha). |
|||
|
|||
### Opções do AJAX |
|||
|
|||
Cada função recebe um **último parâmetro** adicional após seus próprios parâmetros. O último parâmetro é chamado de `ajaxParams`. É um objeto que substitui as opções do AJAX. |
|||
|
|||
**Exemplo: Definir as opções do AJAX `type` e `dataType`** |
|||
|
|||
````js |
|||
acme.bookStore.authors.author |
|||
.delete('7245a066-5457-4941-8aa7-3004778775f0', { |
|||
type: 'POST', |
|||
dataType: 'xml' |
|||
}) |
|||
.then(function() { |
|||
abp.notify.info('Excluído com sucesso!'); |
|||
}); |
|||
```` |
|||
|
|||
Consulte a documentação do [jQuery.ajax](https://api.jquery.com/jQuery.ajax/) para todas as opções disponíveis. |
|||
|
|||
## Veja Também |
|||
|
|||
* [Proxies de Cliente JavaScript Dinâmicos da API](Dynamic-JavaScript-Proxies.md) |
|||
* [Controladores de API Automáticos](../../API/Auto-API-Controllers.md) |
|||
* [Tutorial de Desenvolvimento de Aplicativos da Web](../../Tutorials/Part-1.md) |
|||
@ -0,0 +1,82 @@ |
|||
# Alertas |
|||
|
|||
## Introdução |
|||
|
|||
`abp-alert` é um elemento principal para criar um alerta. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-alert alert-type="Primary"> |
|||
Um alerta primário simples - confira! |
|||
</abp-alert> |
|||
```` |
|||
|
|||
|
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração de [alertas](https://bootstrap-taghelpers.abp.io/Components/Alerts) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### alert-type |
|||
|
|||
Um valor que indica o tipo de alerta. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` (valor padrão) |
|||
* `Primary` |
|||
* `Secondary` |
|||
* `Success` |
|||
* `Danger` |
|||
* `Warning` |
|||
* `Info` |
|||
* `Light` |
|||
* `Dark` |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-alert alert-type="Warning"> |
|||
Um alerta de aviso simples - confira! |
|||
</abp-alert> |
|||
```` |
|||
|
|||
### alert-link |
|||
|
|||
Um valor que fornece links coloridos correspondentes dentro de qualquer alerta. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-alert alert-type="Danger"> |
|||
Um alerta de perigo simples com <a abp-alert-link href="#">um exemplo de link</a>. Clique nele se quiser. |
|||
</abp-alert> |
|||
```` |
|||
|
|||
### dismissible |
|||
|
|||
Um valor para tornar o alerta dispensável. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-alert alert-type="Warning" dismissible="true"> |
|||
Santo guacamole! Você deve verificar alguns desses campos abaixo. |
|||
</abp-alert> |
|||
```` |
|||
|
|||
### Conteúdo adicional |
|||
|
|||
`abp-alert` também pode conter elementos HTML adicionais, como títulos, parágrafos e divisores. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-alert alert-type="Success"> |
|||
<h4>Bom trabalho!</h4> |
|||
<p>Aww yeah, você leu com sucesso esta importante mensagem de alerta. Este texto de exemplo vai ficar um pouco mais longo para que você possa ver como o espaçamento dentro de um alerta funciona com esse tipo de conteúdo.</p> |
|||
<hr> |
|||
<p class="mb-0">Sempre que precisar, certifique-se de usar utilitários de margem para manter as coisas organizadas.</p> |
|||
</abp-alert> |
|||
```` |
|||
@ -0,0 +1,37 @@ |
|||
# Distintivos |
|||
|
|||
## Introdução |
|||
|
|||
`abp-badge` e `abp-badge-pill` são atributos de Tag Helper ABP para tags html `a` e `span`. |
|||
|
|||
Uso básico: |
|||
|
|||
````html |
|||
<span abp-badge="Primary">Primary</span> |
|||
<a abp-badge="Info" href="#">Info</a> |
|||
<a abp-badge-pill="Danger" href="#">Danger</a> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração de [distintivos](https://bootstrap-taghelpers.abp.io/Components/Badges) para vê-los em ação. |
|||
|
|||
### Valores |
|||
|
|||
* Indica o tipo de distintivo. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` |
|||
* `Primary` |
|||
* `Secondary` |
|||
* `Success` |
|||
* `Danger` |
|||
* `Warning` |
|||
* `Info` |
|||
* `Light` |
|||
* `Dark` |
|||
|
|||
Exemplo: |
|||
|
|||
````html |
|||
<span abp-badge-pill="Danger">Danger</span> |
|||
```` |
|||
@ -0,0 +1,18 @@ |
|||
# Blockquote |
|||
|
|||
`abp-blockquote` é o contêiner principal para os itens de blockquote. |
|||
|
|||
Usos básicos: |
|||
|
|||
````html |
|||
<abp-blockquote> |
|||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> |
|||
</abp-blockquote> |
|||
|
|||
<abp-blockquote> |
|||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> |
|||
<footer>Alguém famoso em Título da Fonte</footer> |
|||
</abp-blockquote> |
|||
```` |
|||
|
|||
Ele adiciona a classe `blockquote` ao contêiner principal, também adiciona a classe `blockquote-footer` ao elemento `footer` interno e a classe `mb-0` ao elemento `p` interno. |
|||
@ -0,0 +1,126 @@ |
|||
# Bordas |
|||
|
|||
## Introdução |
|||
|
|||
`abp-border` é um atributo do ABP Tag Helper para estilização de bordas. |
|||
|
|||
Uso básico: |
|||
|
|||
````html |
|||
<span abp-border="Default"></span> |
|||
<span abp-border="Top"></span> |
|||
<span abp-border="Right"></span> |
|||
<span abp-border="Bottom"></span> |
|||
<span abp-border="Left"></span> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração de [bordas](https://bootstrap-taghelpers.abp.io/Components/Borders) para vê-lo em ação. |
|||
|
|||
## Valores |
|||
|
|||
Um valor indica o tipo, posição e a cor da borda. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` |
|||
* `_0` |
|||
* `Primary` |
|||
* `Secondary` |
|||
* `Success` |
|||
* `Danger` |
|||
* `Warning` |
|||
* `Info` |
|||
* `Light` |
|||
* `Dark` |
|||
* `White` |
|||
* `Primary_0` |
|||
* `Secondary_0` |
|||
* `Success_0` |
|||
* `Danger_0` |
|||
* `Warning_0` |
|||
* `Info_0` |
|||
* `Light_0` |
|||
* `Dark_0` |
|||
* `White_0` |
|||
* `Top` |
|||
* `Top_0` |
|||
* `Top_Primary` |
|||
* `Top_Secondary` |
|||
* `Top_Success` |
|||
* `Top_Danger` |
|||
* `Top_Warning` |
|||
* `Top_Info` |
|||
* `Top_Light` |
|||
* `Top_Dark` |
|||
* `Top_White` |
|||
* `Top_Primary_0` |
|||
* `Top_Secondary_0` |
|||
* `Top_Success_0` |
|||
* `Top_Danger_0` |
|||
* `Top_Warning_0` |
|||
* `Top_Info_0` |
|||
* `Top_Light_0` |
|||
* `Top_Dark_0` |
|||
* `Top_White_0` |
|||
* `Right` |
|||
* `Right_0` |
|||
* `Right_Primary` |
|||
* `Right_Secondary` |
|||
* `Right_Success` |
|||
* `Right_Danger` |
|||
* `Right_Warning` |
|||
* `Right_Info` |
|||
* `Right_Light` |
|||
* `Right_Dark` |
|||
* `Right_White` |
|||
* `Right_Primary_0` |
|||
* `Right_Secondary_0` |
|||
* `Right_Success_0` |
|||
* `Right_Danger_0` |
|||
* `Right_Warning_0` |
|||
* `Right_Info_0` |
|||
* `Right_Light_0` |
|||
* `Right_Dark_0` |
|||
* `Right_White_0` |
|||
* `Left` |
|||
* `Left_0` |
|||
* `Left_Primary` |
|||
* `Left_Secondary` |
|||
* `Left_Success` |
|||
* `Left_Danger` |
|||
* `Left_Warning` |
|||
* `Left_Info` |
|||
* `Left_Light` |
|||
* `Left_Dark` |
|||
* `Left_White` |
|||
* `Left_Primary_0` |
|||
* `Left_Secondary_0` |
|||
* `Left_Success_0` |
|||
* `Left_Danger_0` |
|||
* `Left_Warning_0` |
|||
* `Left_Info_0` |
|||
* `Left_Light_0` |
|||
* `Left_Dark_0` |
|||
* `Left_White_0` |
|||
* `Bottom` |
|||
* `Bottom_0` |
|||
* `Bottom_Primary` |
|||
* `Bottom_Secondary` |
|||
* `Bottom_Success` |
|||
* `Bottom_Danger` |
|||
* `Bottom_Warning` |
|||
* `Bottom_Info` |
|||
* `Bottom_Light` |
|||
* `Bottom_Dark` |
|||
* `Bottom_White` |
|||
* `Bottom_Primary_0` |
|||
* `Bottom_Secondary_0` |
|||
* `Bottom_Success_0` |
|||
* `Bottom_Danger_0` |
|||
* `Bottom_Warning_0` |
|||
* `Bottom_Info_0` |
|||
* `Bottom_Light_0` |
|||
* `Bottom_Dark_0` |
|||
* `Bottom_White_0` |
|||
|
|||
(Valores com `_0` no final são para usos [Subtrativos](https://getbootstrap.com/docs/4.0/utilities/borders/#subtractive)) |
|||
@ -0,0 +1,25 @@ |
|||
# Trilha de navegação |
|||
|
|||
## Introdução |
|||
|
|||
`abp-breadcrumb` é o contêiner principal para os itens da trilha de navegação. |
|||
|
|||
Uso básico: |
|||
|
|||
````html |
|||
<abp-breadcrumb> |
|||
<abp-breadcrumb-item href="#" title="Início" /> |
|||
<abp-breadcrumb-item href="#" title="Biblioteca"/> |
|||
<abp-breadcrumb-item title="Página"/> |
|||
</abp-breadcrumb> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração de [trilhas de navegação](https://bootstrap-taghelpers.abp.io/Components/Breadcrumbs) para vê-la em ação. |
|||
|
|||
## Atributos do abp-breadcrumb-item |
|||
|
|||
- **title**: Define o texto do item da trilha de navegação. |
|||
- **active**: Define o item da trilha de navegação ativo. O último item é ativo por padrão, se nenhum outro item estiver ativo. |
|||
- **href**: Um valor que indica se um `abp-breadcrumb-item` possui um link. Deve ser um valor de link em formato de string. |
|||
@ -0,0 +1,37 @@ |
|||
# Grupos de botões |
|||
|
|||
## Introdução |
|||
|
|||
`abp-button-group` é o contêiner principal para elementos de botão agrupados. |
|||
|
|||
Uso básico: |
|||
|
|||
````html |
|||
<abp-button-group> |
|||
<abp-button button-type="Secondary">Esquerda</abp-button> |
|||
<abp-button button-type="Secondary">Meio</abp-button> |
|||
<abp-button button-type="Secondary">Direita</abp-button> |
|||
</abp-button-group> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração de [grupos de botões](https://bootstrap-taghelpers.abp.io/Components/Button-groups) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### direction |
|||
|
|||
Um valor que indica a direção dos botões. Deve ser um dos seguintes valores: |
|||
|
|||
* `Horizontal` (valor padrão) |
|||
* `Vertical` |
|||
|
|||
### size |
|||
|
|||
Um valor que indica o tamanho dos botões no grupo. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` (valor padrão) |
|||
* `Small` |
|||
* `Medium` |
|||
* `Large` |
|||
@ -0,0 +1,98 @@ |
|||
# Botões |
|||
|
|||
## Introdução |
|||
|
|||
`abp-button` é o elemento principal para criar botões. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-button button-type="Primary">Clique em Mim</abp-button> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração de [botões](https://bootstrap-taghelpers.abp.io/Components/Buttons) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### button-type |
|||
|
|||
Um valor que indica o estilo/tipo principal do botão. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` (valor padrão) |
|||
* `Primary` |
|||
* `Secondary` |
|||
* `Success` |
|||
* `Danger` |
|||
* `Warning` |
|||
* `Info` |
|||
* `Light` |
|||
* `Dark` |
|||
* `Outline_Primary` |
|||
* `Outline_Secondary` |
|||
* `Outline_Success` |
|||
* `Outline_Danger` |
|||
* `Outline_Warning` |
|||
* `Outline_Info` |
|||
* `Outline_Light` |
|||
* `Outline_Dark` |
|||
* `Link` |
|||
|
|||
### size |
|||
|
|||
Um valor que indica o tamanho do botão. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` (valor padrão) |
|||
* `Small` |
|||
* `Medium` |
|||
* `Large` |
|||
* `Block` |
|||
* `Block_Small` |
|||
* `Block_Medium` |
|||
* `Block_Large` |
|||
|
|||
### busy-text |
|||
|
|||
Um texto que é mostrado quando o botão está ocupado. |
|||
|
|||
Para tornar o botão ocupado: |
|||
|
|||
````xml |
|||
$('#btnTest').buttonBusy(true); |
|||
```` |
|||
|
|||
Para torná-lo utilizável novamente: |
|||
|
|||
````xml |
|||
$('#btnTest').buttonBusy(false); |
|||
```` |
|||
|
|||
### text |
|||
|
|||
O texto do botão. Isso é um atalho se você simplesmente deseja definir um texto para o botão. Exemplo: |
|||
|
|||
````xml |
|||
<abp-button button-type="Primary" text="Clique em Mim" /> |
|||
```` |
|||
|
|||
Nesse caso, você pode usar uma tag de auto-fechamento para torná-lo mais curto. |
|||
|
|||
### icon |
|||
|
|||
Usado para definir um ícone para o botão. Funciona com as classes de ícone do [Font Awesome](https://fontawesome.com/) por padrão. Exemplo: |
|||
|
|||
````xml |
|||
<abp-button icon="address-card" text="Endereço" /> |
|||
```` |
|||
|
|||
##### icon-type |
|||
|
|||
Se você não deseja usar o font-awesome, você tem duas opções: |
|||
|
|||
1. Defina `icon-type` como `Other` e escreva a classe CSS do ícone de fonte que você está usando. |
|||
2. Se você não usa um ícone de fonte, use as tags de abertura e fechamento manualmente e escreva qualquer código dentro das tags. |
|||
|
|||
### disabled |
|||
|
|||
Defina `true` para desabilitar o botão inicialmente. |
|||
@ -0,0 +1,188 @@ |
|||
# Cartões |
|||
|
|||
## Introdução |
|||
|
|||
`abp-card` é um contêiner de conteúdo derivado do elemento de cartão do Bootstrap. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-card style="width: 18rem;"> |
|||
<img abp-card-image="Top" src="~/imgs/demo/300x200.png"/> |
|||
<abp-card-body> |
|||
<abp-card-title>Título do Cartão</abp-card-title> |
|||
<abp-card-text>Algum texto de exemplo rápido para construir o título do cartão e compor a maior parte do conteúdo do cartão.</abp-card-text> |
|||
<a abp-button="Primary" href="#">Ir para algum lugar</a> |
|||
</abp-card-body> |
|||
</abp-card> |
|||
```` |
|||
|
|||
|
|||
|
|||
##### Usando Títulos, Texto e Links: |
|||
|
|||
As seguintes tags podem ser usadas sob a tag principal `abp-card` |
|||
|
|||
* `abp-card-title` |
|||
* `abp-card-subtitle` |
|||
* `a abp-card-link` |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-card style="width: 18rem;"> |
|||
<abp-card-body> |
|||
<abp-card-title>Título do cartão</abp-card-title> |
|||
<abp-card-subtitle class="mb-2 text-muted">Subtítulo do cartão</abp-card-subtitle> |
|||
<abp-card-text>Algum texto de exemplo rápido para construir o título do cartão e compor a maior parte do conteúdo do cartão.</abp-card-text> |
|||
<a abp-card-link href="#">Link do cartão</a> |
|||
<a abp-card-link href="#">Outro link</a> |
|||
</abp-card-body> |
|||
</abp-card> |
|||
```` |
|||
|
|||
|
|||
|
|||
##### Usando Grupos de Listas: |
|||
|
|||
* `abp-list-group flush="true"` : O atributo `flush` renderiza a classe `list-group-flush` do Bootstrap, que é usada para remover bordas e cantos arredondados para renderizar os itens do grupo de listas de ponta a ponta em um contêiner pai. |
|||
* `abp-list-group-item` |
|||
|
|||
Exemplo completo: |
|||
|
|||
````xml |
|||
<abp-card style="width: 18rem;"> |
|||
<img abp-card-image="Top" src="~/imgs/demo/300x200.png" /> |
|||
<abp-card-body> |
|||
<abp-card-title>Título do Cartão</abp-card-title> |
|||
<abp-card-text>Algum texto de exemplo rápido para construir o título do cartão e compor a maior parte do conteúdo do cartão.</abp-card-text> |
|||
</abp-card-body> |
|||
<abp-list-group flush="true"> |
|||
<abp-list-group-item>Cras justo odio</abp-list-group-item> |
|||
<abp-list-group-item>Dapibus ac facilisis in</abp-list-group-item> |
|||
<abp-list-group-item>Vestibulum at eros</abp-list-group-item> |
|||
</abp-list-group> |
|||
<abp-card-body> |
|||
<a abp-card-link href="#">Link do cartão</a> |
|||
<a abp-card-link href="#">Outro link</a> |
|||
</abp-card-body> |
|||
</abp-card> |
|||
```` |
|||
|
|||
|
|||
|
|||
##### Usando Cabeçalho, Rodapé e Citação: |
|||
|
|||
* `abp-card-header` |
|||
* `abp-card-footer` |
|||
* `abp-blockquote` |
|||
|
|||
Exemplo: |
|||
|
|||
```xml |
|||
<abp-card style="width: 18rem;"> |
|||
<abp-card-header>Destaque</abp-card-header> |
|||
<abp-card-body> |
|||
<abp-card-title>Tratamento especial de título</abp-card-title> |
|||
<abp-card-text>Com texto de suporte abaixo como uma introdução natural a conteúdo adicional.</abp-card-text> |
|||
<a abp-button="Primary" href="#">Ir para algum lugar</a> |
|||
</abp-card-body> |
|||
</abp-card> |
|||
``` |
|||
|
|||
Exemplo de citação: |
|||
|
|||
```xml |
|||
<abp-card> |
|||
<abp-card-header>Citação</abp-card-header> |
|||
<abp-card-body> |
|||
<abp-blockquote> |
|||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> |
|||
<footer>Alguém famoso em Título da Fonte</footer> |
|||
</abp-blockquote> |
|||
</abp-card-body> |
|||
</abp-card> |
|||
``` |
|||
|
|||
Exemplo de rodapé: |
|||
|
|||
```xml |
|||
<abp-card class="text-center"> |
|||
<abp-card-header>Destaque</abp-card-header> |
|||
<abp-card-body> |
|||
<abp-blockquote> |
|||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> |
|||
<footer>Alguém famoso em Título da Fonte</footer> |
|||
</abp-blockquote> |
|||
</abp-card-body> |
|||
<abp-card-footer class="text-muted">2 dias atrás</abp-card-footer> |
|||
</abp-card> |
|||
``` |
|||
|
|||
|
|||
|
|||
## Demonstração |
|||
|
|||
Veja a [página de demonstração de cartões](https://bootstrap-taghelpers.abp.io/Components/Cards) para vê-lo em ação. |
|||
|
|||
## Atributos do abp-card |
|||
|
|||
- **background:** Um valor que indica a cor de fundo do cartão. |
|||
- **text-color**: Um valor que indica a cor do texto dentro do cartão. |
|||
- **border:** Um valor que indica a cor da borda dentro do cartão. |
|||
|
|||
Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` (valor padrão) |
|||
* `Primary` |
|||
* `Secondary` |
|||
* `Success` |
|||
* `Danger` |
|||
* `Warning` |
|||
* `Info` |
|||
* `Light` |
|||
* `Dark` |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-card background="Success" text-color="Danger" border="Dark"> |
|||
```` |
|||
|
|||
### dimensionamento |
|||
|
|||
Os cartões têm largura padrão de 100% e podem ser alterados com CSS personalizado, classes de grade, mixins de grade Sass ou [utilitários](https://getbootstrap.com/docs/4.0/utilities/sizing/). |
|||
|
|||
````xml |
|||
<abp-card style="width: 18rem;"> |
|||
```` |
|||
|
|||
### card-deck e card-columns |
|||
|
|||
`abp-card` também pode ser usado dentro de `card-deck` ou `card-columns`. |
|||
|
|||
````xml |
|||
<div class="card-deck"> |
|||
<abp-card background="Primary"> |
|||
<abp-card-header>Primeiro Deck</abp-card-header> |
|||
<abp-card-body> |
|||
<abp-card-title>Ás</abp-card-title> |
|||
<abp-card-text>Aqui está o conteúdo para Ás.</abp-card-text> |
|||
</abp-card-body> |
|||
</abp-card> |
|||
<abp-card background="Info"> |
|||
<abp-card-header>Segundo Deck</abp-card-header> |
|||
<abp-card-body> |
|||
<abp-card-title>Beta</abp-card-title> |
|||
<abp-card-text>Conteúdo Beta.</abp-card-text> |
|||
</abp-card-body> |
|||
</abp-card> |
|||
<abp-card background="Warning"> |
|||
<abp-card-header>Terceiro Deck</abp-card-header> |
|||
<abp-card-body> |
|||
<abp-card-title>Epsilon</abp-card-title> |
|||
<abp-card-text>Conteúdo para Epsilon.</abp-card-text> |
|||
</abp-card-body> |
|||
</abp-card> |
|||
</div> |
|||
```` |
|||
@ -0,0 +1,71 @@ |
|||
# Carrossel |
|||
|
|||
## Introdução |
|||
|
|||
`abp-carousel` é a tag abp para o elemento carrossel. |
|||
|
|||
Uso básico: |
|||
|
|||
````html |
|||
<abp-carousel> |
|||
<abp-carousel-item src=""></abp-carousel-item> |
|||
<abp-carousel-item src=""></abp-carousel-item> |
|||
<abp-carousel-item src=""></abp-carousel-item> |
|||
</abp-carousel> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página [carousel_demo](https://bootstrap-taghelpers.abp.io/Components/Carousel) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### id |
|||
|
|||
Um valor que define o id do carrossel. Se não for definido, um id gerado será definido quando a tag for criada. |
|||
|
|||
### controls |
|||
|
|||
Um valor para habilitar os controles (botões anterior e próximo) no carrossel. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` |
|||
* `true` |
|||
|
|||
### indicators |
|||
|
|||
Um valor para habilitar os indicadores no carrossel. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` |
|||
* `true` |
|||
|
|||
### crossfade |
|||
|
|||
Um valor para habilitar a animação de fade em vez de slide no carrossel. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` |
|||
* `true` |
|||
|
|||
## Atributos do abp-carousel-item |
|||
|
|||
### caption-title |
|||
|
|||
Um valor que define o título da legenda do item do carrossel. |
|||
|
|||
### caption |
|||
|
|||
Um valor que define a legenda do item do carrossel. |
|||
|
|||
### src |
|||
|
|||
Um valor de link que define a origem da imagem exibida no item do carrossel. |
|||
|
|||
### active |
|||
|
|||
Um valor para definir o item ativo do carrossel. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` |
|||
* `true` |
|||
|
|||
### alt |
|||
|
|||
Um valor que define o texto alternativo para a imagem do item do carrossel quando a imagem não pode ser exibida. |
|||
@ -0,0 +1,92 @@ |
|||
# Colapso |
|||
|
|||
## Introdução |
|||
|
|||
`abp-collapse-body` é o contêiner principal para mostrar e ocultar conteúdo. `abp-collapse-id` é usado para mostrar e ocultar o contêiner de conteúdo. Pode ser acionado tanto com `abp-button` quanto com tags `a`. |
|||
|
|||
Uso básico: |
|||
|
|||
````html |
|||
<abp-button button-type="Primary" abp-collapse-id="collapseExample" text="Botão com data-target" /> |
|||
<a abp-button="Primary" abp-collapse-id="collapseExample"> Link com href </a> |
|||
|
|||
<abp-collapse-body id="collapseExample"> |
|||
Anim pariatur wolf moon tempor,,, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. |
|||
</abp-collapse-body> |
|||
```` |
|||
|
|||
|
|||
|
|||
## Demonstração |
|||
|
|||
Veja a [página de demonstração de colapso](https://bootstrap-taghelpers.abp.io/Components/Collapse) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### show |
|||
|
|||
Um valor que indica se o corpo do colapso será inicializado visível ou oculto. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### multi |
|||
|
|||
Um valor que indica se um `abp-collapse-body` pode ser mostrado ou ocultado por um elemento que pode mostrar/ocultar vários corpos de colapso. Basicamente, esse atributo adiciona a classe "multi-collapse" a `abp-collapse-body`. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<a abp-button="Primary" abp-collapse-id="FirstCollapseExample"> Alternar primeiro elemento </a> |
|||
<abp-button button-type="Primary" abp-collapse-id="SecondCollapseExample" text="Alternar segundo elemento" /> |
|||
<abp-button button-type="Primary" abp-collapse-id="FirstCollapseExample SecondCollapseExample" text="Alternar ambos os elementos" /> |
|||
|
|||
<abp-row class="mt-3"> |
|||
<abp-column size-sm="_6"> |
|||
<abp-collapse-body id="FirstCollapseExample" multi="true"> |
|||
Curabitur porta porttitor libero eu luctus. Praesent ultrices mattis commodo. Integer sodales massa risus, in molestie enim sagittis blandit |
|||
</abp-collapse-body> |
|||
</abp-column> |
|||
<abp-column size-sm="_6"> |
|||
<abp-collapse-body id="SecondCollapseExample" multi="true"> |
|||
Anim pariatur wolf moon tempor,,, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. |
|||
</abp-collapse-body> |
|||
</abp-column> |
|||
</abp-row> |
|||
```` |
|||
|
|||
## Exemplo de acordeão |
|||
|
|||
`abp-accordion` é o contêiner principal para os itens do acordeão. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-accordion> |
|||
<abp-accordion-item title="Item do Grupo Colapsável #1"> |
|||
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry rtat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. |
|||
</abp-accordion-item> |
|||
<abp-accordion-item title="Item do Grupo Colapsável #2"> |
|||
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. |
|||
</abp-accordion-item> |
|||
<abp-accordion-item title="Item do Grupo Colapsável #3"> |
|||
Anim pariatur wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. |
|||
</abp-accordion-item> |
|||
</abp-accordion> |
|||
```` |
|||
|
|||
## Atributos |
|||
|
|||
### active |
|||
|
|||
Um valor que indica se o item do acordeão será inicializado visível ou oculto. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### title |
|||
|
|||
Um valor que indica o título visível do item do acordeão. Deve ser um valor de string. |
|||
@ -0,0 +1,93 @@ |
|||
# Dropdowns |
|||
|
|||
## Introdução |
|||
|
|||
`abp-dropdown` é o contêiner principal para o conteúdo do dropdown. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-dropdown> |
|||
<abp-dropdown-button text="Botão do dropdown" /> |
|||
<abp-dropdown-menu> |
|||
<abp-dropdown-item href="#">Ação</abp-dropdown-item> |
|||
<abp-dropdown-item href="#">Outra ação</abp-dropdown-item> |
|||
<abp-dropdown-item href="#">Algo mais aqui</abp-dropdown-item> |
|||
</abp-dropdown-menu> |
|||
</abp-dropdown> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a [página de demonstração do dropdown](https://bootstrap-taghelpers.abp.io/Components/Dropdowns) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### direction |
|||
|
|||
Um valor que indica em qual direção os botões do dropdown serão exibidos. Deve ser um dos seguintes valores: |
|||
|
|||
* `Down` (valor padrão) |
|||
* `Up` |
|||
* `Right` |
|||
* `Left` |
|||
|
|||
### dropdown-style |
|||
|
|||
Um valor que indica se um `abp-dropdown-button` terá um ícone dividido para o dropdown. Deve ser um dos seguintes valores: |
|||
|
|||
* `Single` (valor padrão) |
|||
* `Split` |
|||
|
|||
## Itens do menu |
|||
|
|||
`abp-dropdown-menu` é o contêiner principal para os itens do menu dropdown. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-dropdown> |
|||
<abp-dropdown-button button-type="Secondary" text="Dropdown"/> |
|||
<abp-dropdown-menu> |
|||
<abp-dropdown-header>Cabeçalho do Dropdown</abp-dropdown-header> |
|||
<abp-dropdown-item href="#">Ação</abp-dropdown-item> |
|||
<abp-dropdown-item active="true" href="#">Ação ativa</abp-dropdown-item> |
|||
<abp-dropdown-item disabled="true" href="#">Ação desativada</abp-dropdown-item> |
|||
<abp-dropdown-divider/> |
|||
<abp-dropdown-item-text>Texto do item do dropdown</abp-dropdown-item-text> |
|||
<abp-dropdown-item href="#">Algo mais aqui</abp-dropdown-item> |
|||
</abp-dropdown-menu> |
|||
</abp-dropdown> |
|||
```` |
|||
|
|||
## Atributos |
|||
|
|||
### align |
|||
|
|||
Um valor que indica em qual direção os itens do `abp-dropdown-menu` serão alinhados. Deve ser um dos seguintes valores: |
|||
|
|||
* `Start` (valor padrão) |
|||
* `End` |
|||
|
|||
### Conteúdo adicional |
|||
|
|||
`abp-dropdown-menu` também pode conter elementos HTML adicionais como títulos, parágrafos, divisores ou elementos de formulário. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-dropdown > |
|||
<abp-dropdown-button button-type="Secondary" text="Dropdown com Formulário"/> |
|||
<abp-dropdown-menu> |
|||
<form class="px-4 py-3"> |
|||
<abp-input asp-for="EmailAddress"></abp-input> |
|||
<abp-input asp-for="Password"></abp-input> |
|||
<abp-input asp-for="RememberMe"></abp-input> |
|||
<abp-button button-type="Primary" text="Entrar" type="submit" /> |
|||
</form> |
|||
<abp-dropdown-divider></abp-dropdown-divider> |
|||
<abp-dropdown-item href="#">Novo por aqui? Cadastre-se</abp-dropdown-item> |
|||
<abp-dropdown-item href="#">Esqueceu a senha?</abp-dropdown-item> |
|||
</abp-dropdown-menu> |
|||
</abp-dropdown> |
|||
```` |
|||
@ -0,0 +1,281 @@ |
|||
# Formulários Dinâmicos |
|||
|
|||
## Introdução |
|||
|
|||
`abp-dynamic-form` cria um formulário bootstrap para um modelo C# fornecido. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-dynamic-form abp-model="@Model.MyDetailedModel"/> |
|||
```` |
|||
|
|||
Modelo: |
|||
|
|||
````csharp |
|||
public class DynamicFormsModel : PageModel |
|||
{ |
|||
[BindProperty] |
|||
public DetailedModel MyDetailedModel { get; set; } |
|||
|
|||
public List<SelectListItem> CountryList { get; set; } = new List<SelectListItem> |
|||
{ |
|||
new SelectListItem { Value = "CA", Text = "Canadá"}, |
|||
new SelectListItem { Value = "US", Text = "EUA"}, |
|||
new SelectListItem { Value = "UK", Text = "Reino Unido"}, |
|||
new SelectListItem { Value = "RU", Text = "Rússia"} |
|||
}; |
|||
|
|||
public void OnGet() |
|||
{ |
|||
MyDetailedModel = new DetailedModel |
|||
{ |
|||
Name = "", |
|||
Description = "Lorem ipsum dolor sit amet.", |
|||
IsActive = true, |
|||
Age = 65, |
|||
Day = DateTime.Now, |
|||
MyCarType = CarType.Coupe, |
|||
YourCarType = CarType.Sedan, |
|||
Country = "RU", |
|||
NeighborCountries = new List<string>() { "UK", "CA" } |
|||
}; |
|||
} |
|||
|
|||
public class DetailedModel |
|||
{ |
|||
[Required] |
|||
[Placeholder("Digite seu nome...")] |
|||
[Display(Name = "Nome")] |
|||
public string Name { get; set; } |
|||
|
|||
[TextArea(Rows = 4)] |
|||
[Display(Name = "Descrição")] |
|||
[InputInfoText("Descreva-se")] |
|||
public string Description { get; set; } |
|||
|
|||
[Required] |
|||
[DataType(DataType.Password)] |
|||
[Display(Name = "Senha")] |
|||
public string Password { get; set; } |
|||
|
|||
[Display(Name = "Ativo")] |
|||
public bool IsActive { get; set; } |
|||
|
|||
[Required] |
|||
[Display(Name = "Idade")] |
|||
public int Age { get; set; } |
|||
|
|||
[Required] |
|||
[Display(Name = "Meu Tipo de Carro")] |
|||
public CarType MyCarType { get; set; } |
|||
|
|||
[Required] |
|||
[AbpRadioButton(Inline = true)] |
|||
[Display(Name = "Seu Tipo de Carro")] |
|||
public CarType YourCarType { get; set; } |
|||
|
|||
[DataType(DataType.Date)] |
|||
[Display(Name = "Dia")] |
|||
public DateTime Day { get; set; } |
|||
|
|||
[SelectItems(nameof(CountryList))] |
|||
[Display(Name = "País")] |
|||
public string Country { get; set; } |
|||
|
|||
[SelectItems(nameof(CountryList))] |
|||
[Display(Name = "Países Vizinhos")] |
|||
public List<string> NeighborCountries { get; set; } |
|||
} |
|||
|
|||
public enum CarType |
|||
{ |
|||
Sedan, |
|||
Hatchback, |
|||
StationWagon, |
|||
Coupe |
|||
} |
|||
} |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a [página de demonstração de formulários dinâmicos](https://bootstrap-taghelpers.abp.io/Components/DynamicForms) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### abp-model |
|||
|
|||
Define o modelo C# para o formulário dinâmico. As propriedades deste modelo são convertidas em campos de entrada no formulário. |
|||
|
|||
### column-size |
|||
|
|||
Aqui, use 'col-sm' para definir o tamanho. Ao definir essa propriedade, 'col-12' será adicionado ao mesmo tempo. |
|||
|
|||
### submit-button |
|||
|
|||
Pode ser `True` ou `False`. |
|||
|
|||
Se `True`, um botão de envio será gerado na parte inferior do formulário. |
|||
|
|||
O valor padrão é `False`. |
|||
|
|||
### required-symbols |
|||
|
|||
Pode ser `True` ou `False`. |
|||
|
|||
Se `True`, as entradas obrigatórias terão um símbolo (*) que indica que são obrigatórias. |
|||
|
|||
O valor padrão é `True`. |
|||
|
|||
## Posicionamento do Conteúdo do Formulário |
|||
|
|||
Por padrão, `abp-dynamic-form` limpa o HTML interno e coloca os campos de entrada nele. Se você quiser adicionar conteúdo adicional ao formulário dinâmico ou colocar os campos de entrada em uma área específica, você pode usar a tag `<abp-form-content />`. Essa tag será substituída pelo conteúdo do formulário e o restante do HTML interno da tag `abp-dynamic-form` permanecerá inalterado. |
|||
|
|||
Uso: |
|||
|
|||
````xml |
|||
<abp-dynamic-form abp-model="@Model.MyExampleModel"> |
|||
<div> |
|||
Algum conteúdo.... |
|||
</div> |
|||
<div class="input-area"> |
|||
<abp-form-content /> |
|||
</div> |
|||
<div> |
|||
Mais algum conteúdo.... |
|||
</div> |
|||
</abp-dynamic-form> |
|||
```` |
|||
|
|||
## Ordem de Entrada |
|||
|
|||
`abp-dynamic-form` ordena as propriedades pelo atributo `DisplayOrder` e, em seguida, pela ordem das propriedades na classe do modelo. |
|||
|
|||
O número padrão do atributo `DisplayOrder` é 10000 para todas as propriedades. |
|||
|
|||
Veja o exemplo abaixo: |
|||
|
|||
````csharp |
|||
public class OrderExampleModel |
|||
{ |
|||
[DisplayOrder(10004)] |
|||
public string Name{ get; set; } |
|||
|
|||
[DisplayOrder(10005)] |
|||
public string Surname{ get; set; } |
|||
|
|||
//Padrão 10000 |
|||
public string EmailAddress { get; set; } |
|||
|
|||
[DisplayOrder(10003)] |
|||
public string PhoneNumber { get; set; } |
|||
|
|||
[DisplayOrder(9999)] |
|||
public string City { get; set; } |
|||
} |
|||
```` |
|||
|
|||
Neste exemplo, os campos de entrada serão exibidos com a seguinte ordem: `City` > `EmailAddress` > `PhoneNumber` > `Name` > `Surname`. |
|||
|
|||
## Ignorando uma propriedade |
|||
|
|||
Por padrão, `abp-dynamic-form` gera uma entrada para cada propriedade na classe do modelo. Se você quiser ignorar uma propriedade, use o atributo `DynamicFormIgnore`. |
|||
|
|||
Veja o exemplo abaixo: |
|||
|
|||
````csharp |
|||
public class MyModel |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
[DynamicFormIgnore] |
|||
public string Surname { get; set; } |
|||
} |
|||
```` |
|||
|
|||
Neste exemplo, nenhuma entrada será gerada para a propriedade `Surname`. |
|||
|
|||
## Indicando Caixa de Texto, Grupo de Rádio e Combobox |
|||
|
|||
Se você leu o documento [Elementos de Formulário](Form-elements.md), você percebeu que as tags `abp-radio` e `abp-select` são muito semelhantes no modelo C#. Portanto, temos que usar o atributo `[AbpRadioButton()]` para informar ao `abp-dynamic-form` qual das suas propriedades será um grupo de rádio e qual será uma combobox. Veja o exemplo abaixo: |
|||
|
|||
````xml |
|||
<abp-dynamic-form abp-model="@Model.MyDetailedModel"/> |
|||
```` |
|||
|
|||
Modelo: |
|||
|
|||
````csharp |
|||
public class DynamicFormsModel : PageModel |
|||
{ |
|||
[BindProperty] |
|||
public DetailedModel MyDetailedModel { get; set; } |
|||
|
|||
public List<SelectListItem> CountryList { get; set; } = new List<SelectListItem> |
|||
{ |
|||
new SelectListItem { Value = "CA", Text = "Canadá"}, |
|||
new SelectListItem { Value = "US", Text = "EUA"}, |
|||
new SelectListItem { Value = "UK", Text = "Reino Unido"}, |
|||
new SelectListItem { Value = "RU", Text = "Rússia"} |
|||
}; |
|||
|
|||
public void OnGet() |
|||
{ |
|||
MyDetailedModel = new DetailedModel |
|||
{ |
|||
ComboCarType = CarType.Coupe, |
|||
RadioCarType = CarType.Sedan, |
|||
ComboCountry = "RU", |
|||
RadioCountry = "UK" |
|||
}; |
|||
} |
|||
|
|||
public class DetailedModel |
|||
{ |
|||
public CarType ComboCarType { get; set; } |
|||
|
|||
[AbpRadioButton(Inline = true)] |
|||
public CarType RadioCarType { get; set; } |
|||
|
|||
[SelectItems(nameof(CountryList))] |
|||
public string ComboCountry { get; set; } |
|||
|
|||
[AbpRadioButton()] |
|||
[SelectItems(nameof(CountryList))] |
|||
public string RadioCountry { get; set; } |
|||
} |
|||
|
|||
public enum CarType |
|||
{ |
|||
Sedan, |
|||
Hatchback, |
|||
StationWagon, |
|||
Coupe |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Como você pode ver no exemplo acima: |
|||
|
|||
* Se `[AbpRadioButton()]` for usado em uma propriedade **Enum**, será um grupo de rádio. Caso contrário, será uma combobox. |
|||
* Se `[SelectItems()]` e `[AbpRadioButton()]` forem usados em uma propriedade, será um grupo de rádio. |
|||
* Se apenas `[SelectItems()]` for usado em uma propriedade, será uma combobox. |
|||
* Se nenhum desses atributos for usado em uma propriedade, será uma caixa de texto. |
|||
|
|||
## Localização |
|||
|
|||
`abp-dynamic-form` também lida com localização. |
|||
|
|||
Por padrão, ele tentará encontrar as chaves de localização "DisplayName:{PropertyName}" ou "{PropertyName}" e definir o valor de localização como rótulo de entrada. |
|||
|
|||
Você pode definir isso você mesmo usando o atributo `[Display()]` do Asp.Net Core. Você pode usar uma chave de localização neste atributo. Veja o exemplo abaixo: |
|||
|
|||
````csharp |
|||
[Display(Name = "Nome")] |
|||
public string Name { get; set; } |
|||
```` |
|||
|
|||
## Veja Também |
|||
|
|||
* [Elementos de Formulário](Form-elements.md) |
|||
@ -0,0 +1,14 @@ |
|||
# Figuras |
|||
|
|||
`abp-figure` é o contêiner principal para os itens de figura do bootstrap. |
|||
|
|||
Uso básico: |
|||
|
|||
````html |
|||
<abp-figure> |
|||
<abp-image src="..." class="img-fluid rounded" alt="Uma imagem de espaço reservado quadrado genérico com cantos arredondados em uma figura."> |
|||
<abp-figcaption class="text-end">Uma legenda para a imagem acima.</abp-figcaption> |
|||
</abp-figure> |
|||
```` |
|||
|
|||
Ele adiciona a classe `figure` ao contêiner principal, também adiciona a classe `figure-img` ao elemento `abp-image` interno e a classe `figure-caption` ao elemento `abp-figcaption` interno. |
|||
@ -0,0 +1,435 @@ |
|||
# Elementos de Formulário |
|||
|
|||
## Introdução |
|||
|
|||
O Abp fornece ajudantes de tag de entrada de formulário para facilitar a construção de formulários. |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração dos [elementos de formulário](https://bootstrap-taghelpers.abp.io/Components/FormElements) para vê-los em ação. |
|||
|
|||
## abp-input |
|||
|
|||
A tag `abp-input` cria um campo de entrada de formulário do Bootstrap para uma propriedade C# específica. Ela usa o [Asp.Net Core Input Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-7.0#the-input-tag-helper) em segundo plano, portanto, todos os atributos de anotação de dados da tag `input` do Asp.Net Core também são válidos para `abp-input`. |
|||
|
|||
Uso: |
|||
|
|||
````xml |
|||
<abp-input asp-for="@Model.MyModel.Name"/> |
|||
<abp-input asp-for="@Model.MyModel.Description"/> |
|||
<abp-input asp-for="@Model.MyModel.Password"/> |
|||
<abp-input asp-for="@Model.MyModel.IsActive"/> |
|||
```` |
|||
|
|||
Modelo: |
|||
|
|||
````csharp |
|||
public class FormElementsModel : PageModel |
|||
{ |
|||
public SampleModel MyModel { get; set; } |
|||
|
|||
public void OnGet() |
|||
{ |
|||
MyModel = new SampleModel(); |
|||
} |
|||
|
|||
public class SampleModel |
|||
{ |
|||
[Required] |
|||
[Placeholder("Digite seu nome...")] |
|||
[InputInfoText("Qual é o seu nome?")] |
|||
public string Name { get; set; } |
|||
|
|||
[Required] |
|||
[FormControlSize(AbpFormControlSize.Large)] |
|||
public string SurName { get; set; } |
|||
|
|||
[TextArea(Rows = 4)] |
|||
public string Description { get; set; } |
|||
|
|||
[Required] |
|||
[DataType(DataType.Password)] |
|||
public string Password { get; set; } |
|||
|
|||
public bool IsActive { get; set; } |
|||
} |
|||
} |
|||
```` |
|||
|
|||
### Atributos |
|||
|
|||
Você pode definir alguns atributos na propriedade C# ou diretamente na tag HTML. Se você for usar essa propriedade em um [abp-dynamic-form](Dynamic-Forms.md), só poderá definir essas propriedades por meio de atributos de propriedade. |
|||
|
|||
#### Atributos de Propriedade |
|||
|
|||
- `[TextArea()]`: Converte a entrada em uma área de texto. |
|||
|
|||
* `[Placeholder()]`: Define a descrição da entrada. Você pode usar uma chave de localização diretamente. |
|||
* `[InputInfoText()]`: Define o texto para a entrada. Você pode usar uma chave de localização diretamente. |
|||
* `[FormControlSize()]`: Define o tamanho do elemento de wrapper form-control. Os valores disponíveis são: |
|||
- `AbpFormControlSize.Default` |
|||
- `AbpFormControlSize.Small` |
|||
- `AbpFormControlSize.Medium` |
|||
- `AbpFormControlSize.Large` |
|||
* `[DisabledInput]` : Define a entrada como desabilitada. |
|||
* `[ReadOnlyInput]`: Define a entrada como somente leitura. |
|||
|
|||
#### Atributos de Tag |
|||
|
|||
* `info`: Define o texto para a entrada. Você pode usar uma chave de localização diretamente. |
|||
* `auto-focus`: Permite que o navegador defina o foco no elemento quando o valor for verdadeiro. |
|||
* `size`: Define o tamanho do elemento de wrapper form-control. Os valores disponíveis são: |
|||
- `AbpFormControlSize.Default` |
|||
- `AbpFormControlSize.Small` |
|||
- `AbpFormControlSize.Medium` |
|||
- `AbpFormControlSize.Large` |
|||
* `disabled`: Define a entrada como desabilitada. |
|||
* `readonly`: Define a entrada como somente leitura. |
|||
* `label`: Define o rótulo da entrada. |
|||
* `required-symbol`: Adiciona o símbolo de obrigatório `(*)` ao rótulo quando a entrada é obrigatória. O valor padrão é `True`. |
|||
* `floating-label`: Define o rótulo como rótulo flutuante. O valor padrão é `False`. |
|||
|
|||
Os atributos `asp-format`, `name` e `value` do [Asp.Net Core Input Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-7.0#the-input-tag-helper) também são válidos para o ajudante de tag `abp-input`. |
|||
|
|||
### Rótulo e Localização |
|||
|
|||
Você pode definir o rótulo da entrada de várias maneiras: |
|||
|
|||
- Você pode usar o atributo `Label` para definir o rótulo diretamente. Essa propriedade não localiza automaticamente o texto. Para localizar o rótulo, use `label="@L["{LocalizationKey}"].Value"`. |
|||
- Você pode defini-lo usando o atributo `[Display(name="{LocalizationKey}")]` do ASP.NET Core. |
|||
- Você pode deixar o **abp** encontrar a chave de localização para a propriedade. Ele tentará encontrar as chaves de localização "DisplayName:{PropertyName}" ou "{PropertyName}", se os atributos `label` ou `[DisplayName]` não estiverem definidos. |
|||
|
|||
## abp-select |
|||
|
|||
A tag `abp-select` cria um seletor de formulário do Bootstrap para uma propriedade C# específica. Ela usa o [ASP.NET Core Select Tag Helper](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-select-tag-helper) em segundo plano, portanto, todos os atributos de anotação de dados da tag `select` do ASP.NET Core também são válidos para `abp-select`. |
|||
|
|||
A tag `abp-select` precisa de uma lista de `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem` para funcionar. Ela pode ser fornecida pelo atributo `asp-items` na tag ou pelo atributo `[SelectItems()]` na propriedade C# (se você estiver usando [abp-dynamic-form](Dynamic-Forms.md), o atributo C# é a única opção). |
|||
|
|||
O `abp-select` suporta seleção múltipla. |
|||
|
|||
O `abp-select` cria automaticamente uma lista de seleção para propriedades **Enum**. Nenhum dado extra é necessário. Se a propriedade for nula, uma chave e valor vazios serão adicionados no topo da lista gerada automaticamente. |
|||
|
|||
Uso: |
|||
|
|||
````xml |
|||
<abp-select asp-for="@Model.MyModel.City" asp-items="@Model.CityList"/> |
|||
|
|||
<abp-select asp-for="@Model.MyModel.AnotherCity"/> |
|||
|
|||
<abp-select asp-for="@Model.MyModel.MultipleCities" asp-items="@Model.CityList"/> |
|||
|
|||
<abp-select asp-for="@Model.MyModel.MyCarType"/> |
|||
|
|||
<abp-select asp-for="@Model.MyModel.MyNullableCarType"/> |
|||
```` |
|||
|
|||
Modelo: |
|||
|
|||
````csharp |
|||
public class FormElementsModel : PageModel |
|||
{ |
|||
public SampleModel MyModel { get; set; } |
|||
|
|||
public List<SelectListItem> CityList { get; set; } |
|||
|
|||
public void OnGet() |
|||
{ |
|||
MyModel = new SampleModel(); |
|||
|
|||
CityList = new List<SelectListItem> |
|||
{ |
|||
new SelectListItem { Value = "NY", Text = "Nova York"}, |
|||
new SelectListItem { Value = "LDN", Text = "Londres"}, |
|||
new SelectListItem { Value = "IST", Text = "Istambul"}, |
|||
new SelectListItem { Value = "MOS", Text = "Moscou"} |
|||
}; |
|||
} |
|||
|
|||
public class SampleModel |
|||
{ |
|||
public string City { get; set; } |
|||
|
|||
[SelectItems(nameof(CityList))] |
|||
public string AnotherCity { get; set; } |
|||
|
|||
public List<string> MultipleCities { get; set; } |
|||
|
|||
public CarType MyCarType { get; set; } |
|||
|
|||
public CarType? MyNullableCarType { get; set; } |
|||
} |
|||
|
|||
public enum CarType |
|||
{ |
|||
Sedan, |
|||
Hatchback, |
|||
StationWagon, |
|||
Coupe |
|||
} |
|||
} |
|||
```` |
|||
|
|||
### Atributos |
|||
|
|||
Você pode definir alguns atributos na propriedade C# ou diretamente na tag HTML. Se você for usar essa propriedade em um [abp-dynamic-form](Dynamic-Forms.md), só poderá definir essas propriedades por meio de atributos de propriedade. |
|||
|
|||
#### Atributos de Propriedade |
|||
|
|||
* `[SelectItems()]`: Define os dados do seletor. O parâmetro deve ser o nome da lista de dados. (veja o exemplo acima) |
|||
|
|||
- `[InputInfoText()]`: Define o texto para a entrada. Você pode usar uma chave de localização diretamente. |
|||
- `[FormControlSize()]`: Define o tamanho do elemento de wrapper form-control. Os valores disponíveis são: |
|||
- `AbpFormControlSize.Default` |
|||
- `AbpFormControlSize.Small` |
|||
- `AbpFormControlSize.Medium` |
|||
- `AbpFormControlSize.Large` |
|||
|
|||
#### Atributos de Tag |
|||
|
|||
- `asp-items`: Define os dados do seletor. Isso deve ser uma lista de SelectListItem. |
|||
- `info`: Define o texto para a entrada. Você pode usar uma chave de localização diretamente. |
|||
- `size`: Define o tamanho do elemento de wrapper form-control. Os valores disponíveis são: |
|||
- `AbpFormControlSize.Default` |
|||
- `AbpFormControlSize.Small` |
|||
- `AbpFormControlSize.Medium` |
|||
- `AbpFormControlSize.Large` |
|||
- `label`: Define o rótulo da entrada. |
|||
- `required-symbol`: Adiciona o símbolo de obrigatório `(*)` ao rótulo quando a entrada é obrigatória. O valor padrão é `True`. |
|||
|
|||
### Rótulo e Localização |
|||
|
|||
Você pode definir o rótulo da entrada de várias maneiras: |
|||
|
|||
- Você pode usar o atributo `Label` e definir diretamente o rótulo. Mas isso não localiza automaticamente sua chave de localização. Portanto, use-o como `label="@L["{LocalizationKey}"].Value".` |
|||
- Você pode defini-lo usando o atributo `[Display(name="{LocalizationKey}")]` do ASP.NET Core. |
|||
- Você pode deixar o **abp** encontrar a chave de localização para a propriedade. Ele tentará encontrar as chaves de localização "DisplayName:{PropertyName}" ou "{PropertyName}". |
|||
|
|||
As localizações dos valores do combobox são definidas pelo `abp-select` para a propriedade **Enum**. Ele procura pelas chaves de localização "{EnumTypeName}.{EnumPropertyName}" ou "{EnumPropertyName}". Por exemplo, no exemplo acima, ele usará as chaves "CarType.StationWagon" ou "StationWagon" para localizar os valores do combobox. |
|||
|
|||
## abp-radio |
|||
|
|||
A tag `abp-radio` cria um grupo de rádio do Bootstrap para uma propriedade C# específica. O uso é muito semelhante à tag `abp-select`. |
|||
|
|||
Uso: |
|||
|
|||
````xml |
|||
<abp-radio asp-for="@Model.MyModel.CityRadio" asp-items="@Model.CityList" inline="true"/> |
|||
|
|||
<abp-radio asp-for="@Model.MyModel.CityRadio2"/> |
|||
```` |
|||
|
|||
Modelo: |
|||
|
|||
````csharp |
|||
public class FormElementsModel : PageModel |
|||
{ |
|||
public SampleModel MyModel { get; set; } |
|||
|
|||
public List<SelectListItem> CityList { get; set; } = new List<SelectListItem> |
|||
{ |
|||
new SelectListItem { Value = "NY", Text = "Nova York"}, |
|||
new SelectListItem { Value = "LDN", Text = "Londres"}, |
|||
new SelectListItem { Value = "IST", Text = "Istambul"}, |
|||
new SelectListItem { Value = "MOS", Text = "Moscou"} |
|||
}; |
|||
|
|||
public void OnGet() |
|||
{ |
|||
MyModel = new SampleModel(); |
|||
MyModel.CityRadio = "IST"; |
|||
MyModel.CityRadio2 = "MOS"; |
|||
} |
|||
|
|||
public class SampleModel |
|||
{ |
|||
public string CityRadio { get; set; } |
|||
|
|||
[SelectItems(nameof(CityList))] |
|||
public string CityRadio2 { get; set; } |
|||
} |
|||
} |
|||
```` |
|||
|
|||
### Atributos |
|||
|
|||
Você pode definir alguns atributos na propriedade C# ou diretamente na tag HTML. Se você for usar essa propriedade em um [abp-dynamic-form](Dynamic-Forms.md), só poderá definir essas propriedades por meio de atributos de propriedade. |
|||
|
|||
#### Atributos de Propriedade |
|||
|
|||
- `[SelectItems()]`: Define os dados do seletor. O parâmetro deve ser o nome da lista de dados. (veja o exemplo acima) |
|||
|
|||
#### Atributos de Tag |
|||
|
|||
- `asp-items`: Define os dados do seletor. Isso deve ser uma lista de SelectListItem. |
|||
- `Inline`: Se verdadeiro, os botões de rádio serão exibidos em uma única linha, um ao lado do outro. Se falso, eles serão exibidos um abaixo do outro. |
|||
|
|||
## abp-date-picker & abp-date-range-picker |
|||
|
|||
As tags `abp-date-picker` e `abp-date-range-picker` criam um seletor de data do Bootstrap para uma propriedade C# específica. O `abp-date-picker` é para seleção de uma única data, o `abp-date-range-picker` é para seleção de um intervalo de datas. Elas usam o plugin jQuery [datepicker](https://www.daterangepicker.com/). |
|||
|
|||
Uso: |
|||
|
|||
````xml |
|||
<abp-date-picker asp-for="@Model.MyModel.MyDate" /> |
|||
<abp-date-range-picker asp-for-start="@Model.MyModel.MyDateRangeStart" asp-for-end="@Model.MyModel.MyDateRangeEnd" /> |
|||
<abp-dynamic-form abp-model="DynamicFormExample"></abp-dynamic-form> |
|||
```` |
|||
|
|||
Modelo: |
|||
|
|||
````csharp |
|||
public class FormElementsModel : PageModel |
|||
{ |
|||
public SampleModel MyModel { get; set; } |
|||
|
|||
public DynamicForm DynamicFormExample { get; set; } |
|||
|
|||
public void OnGet() |
|||
{ |
|||
MyModel = new SampleModel(); |
|||
|
|||
DynamicFormExample = new DynamicForm(); |
|||
} |
|||
|
|||
public class SampleModel |
|||
{ |
|||
public DateTime MyDate { get; set; } |
|||
|
|||
public DateTime MyDateRangeStart { get; set; } |
|||
|
|||
public DateTime MyDateRangeEnd { get; set; } |
|||
} |
|||
|
|||
public class DynamicForm |
|||
{ |
|||
[DateRangePicker("MyPicker",true)] |
|||
public DateTime StartDate { get; set; } |
|||
|
|||
[DateRangePicker("MyPicker",false)] |
|||
[DatePickerOptions(nameof(DatePickerOptions))] |
|||
public DateTime EndDate { get; set; } |
|||
|
|||
public DateTime DateTime { get; set; } |
|||
|
|||
public DynamicForm() |
|||
{ |
|||
StartDate = DateTime.Now; |
|||
EndDate = DateTime.Now; |
|||
DateTime = DateTime.Now; |
|||
} |
|||
} |
|||
|
|||
public AbpDatePickerOptions DatePickerOptions { get; set; } |
|||
} |
|||
```` |
|||
|
|||
### Atributos |
|||
|
|||
Você pode definir alguns atributos na propriedade C# ou diretamente na tag HTML. Se você for usar essa propriedade em um [abp-dynamic-form](Dynamic-Forms.md), só poderá definir essas propriedades por meio de atributos de propriedade. |
|||
|
|||
#### Atributos de Propriedade |
|||
|
|||
* `[Placeholder()]`: Define a descrição da entrada. Você pode usar uma chave de localização diretamente. |
|||
* `[InputInfoText()]`: Define o texto para a entrada. Você pode usar uma chave de localização diretamente. |
|||
* `[FormControlSize()]`: Define o tamanho do elemento de wrapper form-control. Os valores disponíveis são: |
|||
- `AbpFormControlSize.Default` |
|||
- `AbpFormControlSize.Small` |
|||
- `AbpFormControlSize.Medium` |
|||
- `AbpFormControlSize.Large` |
|||
* `[DisabledInput]` : Define a entrada como desabilitada. |
|||
* `[ReadOnlyInput]`: Define a entrada como somente leitura. |
|||
- `[DatePickerOptions()]`: Define as opções predefinidas do seletor de data. O parâmetro deve ser o nome da propriedade de opções (veja o exemplo acima). Veja as opções de [datepicker disponíveis](https://www.daterangepicker.com/#options). Você pode usar uma chave de localização diretamente. |
|||
|
|||
##### abp-date-picker |
|||
`[DatePicker]` : Define a entrada como seletor de data. Especialmente para propriedades de string. |
|||
|
|||
##### abp-date-range-picker |
|||
`[DateRangePicker()]` : Define o ID do seletor para o seletor de intervalo de datas. Você pode definir a propriedade como uma data de início definindo IsStart=true ou deixá-la como padrão/falso para definir como uma data de término. |
|||
|
|||
#### Atributos de Tag |
|||
|
|||
* `info`: Define o texto para a entrada. Você pode usar uma chave de localização diretamente. |
|||
* `auto-focus`: Permite que o navegador defina o foco no elemento quando o valor for verdadeiro. |
|||
* `size`: Define o tamanho do elemento de wrapper form-control. Os valores disponíveis são: |
|||
- `AbpFormControlSize.Default` |
|||
- `AbpFormControlSize.Small` |
|||
- `AbpFormControlSize.Medium` |
|||
- `AbpFormControlSize.Large` |
|||
* `disabled`: Define a entrada como desabilitada. |
|||
* `readonly`: Define a entrada como somente leitura. |
|||
* `label`: Define o rótulo da entrada. |
|||
* `required-symbol`: Adiciona o símbolo de obrigatório `(*)` ao rótulo quando a entrada é obrigatória. O valor padrão é `True`. |
|||
* `open-button`: Um botão para abrir o seletor de data será adicionado quando for `True`. O valor padrão é `True`. |
|||
* `clear-button`: Um botão para limpar o seletor de data será adicionado quando for `True`. O valor padrão é `True`. |
|||
* `single-open-and-clear-button`: Mostra os botões de abrir e limpar em um único botão quando for `True`. O valor padrão é `True`. |
|||
* `is-utc`: Converte a data para UTC quando for `True`. O valor padrão é `False`. |
|||
* `is-iso`: Converte a data para o formato ISO quando for `True`. O valor padrão é `False`. |
|||
* `visible-date-format`: Define o formato de data da entrada. O formato padrão é o formato de data da cultura do usuário. Você precisa fornecer uma convenção de formato de data JavaScript. Por exemplo: `YYYY-MM-DDTHH:MM:SSZ`. |
|||
* `input-date-format`: Define o formato de data do input oculto para compatibilidade com o backend. O formato padrão é `YYYY-MM-DD`. Você precisa fornecer uma convenção de formato de data JavaScript. Por exemplo: `YYYY-MM-DDTHH:MM:SSZ`. |
|||
* `date-separator`: Define um caractere para separar as datas de início e término. O valor padrão é `-` |
|||
* Outros atributos não mapeados serão adicionados automaticamente ao elemento de entrada como estão. Veja as opções de [datepicker disponíveis](https://www.daterangepicker.com/#options). Por exemplo: `data-start-date="2020-01-01"` |
|||
|
|||
##### abp-date-picker |
|||
|
|||
* `asp-date`: Define o valor da data. Isso deve ser um valor `DateTime`, `DateTime?`, `DateTimeOffset`, `DateTimeOffset?` ou `string`. |
|||
|
|||
##### abp-date-range-picker |
|||
|
|||
* `asp-for-start`: Define o valor da data de início. Isso deve ser um valor `DateTime`, `DateTime?`, `DateTimeOffset`, `DateTimeOffset?` ou `string`. |
|||
* `asp-for-end`: Define o valor da data de término. Isso deve ser um valor `DateTime`, `DateTime?`, `DateTimeOffset`, `DateTimeOffset?` ou `string`. |
|||
|
|||
### Rótulo e Localização |
|||
|
|||
Você pode definir o rótulo da entrada de várias maneiras: |
|||
|
|||
- Você pode usar o atributo `Label` para definir o rótulo diretamente. Essa propriedade não localiza automaticamente o texto. Para localizar o rótulo, use `label="@L["{LocalizationKey}"].Value"`. |
|||
- Você pode defini-lo usando o atributo `[Display(name="{LocalizationKey}")]` do ASP.NET Core. |
|||
- Você pode deixar o **abp** encontrar a chave de localização para a propriedade. Ele tentará encontrar as chaves de localização "DisplayName:{PropertyName}" ou "{PropertyName}". |
|||
|
|||
### Uso em JavaScript |
|||
|
|||
````javascript |
|||
var newPicker = abp.libs.bootstrapDateRangePicker.createDateRangePicker( |
|||
{ |
|||
label: "Novo Seletor", |
|||
} |
|||
); |
|||
newPicker.insertAfter($('body')); |
|||
```` |
|||
|
|||
````javascript |
|||
var newPicker = abp.libs.bootstrapDateRangePicker.createSinglePicker( |
|||
{ |
|||
label: "Novo Seletor", |
|||
} |
|||
); |
|||
newPicker.insertAfter($('body')); |
|||
```` |
|||
|
|||
#### Opções |
|||
|
|||
* `label`: Define o rótulo da entrada. |
|||
* `placeholder`: Define o espaço reservado da entrada. |
|||
* `value`: Define o valor da entrada. |
|||
* `name`: Define o nome da entrada. |
|||
* `id`: Define o ID da entrada. |
|||
* `required`: Define a entrada como obrigatória. |
|||
* `disabled`: Define a entrada como desabilitada. |
|||
* `readonly`: Define a entrada como somente leitura. |
|||
* `size`: Define o tamanho do elemento de wrapper form-control. Os valores disponíveis são: |
|||
- `AbpFormControlSize.Default` |
|||
- `AbpFormControlSize.Small` |
|||
- `AbpFormControlSize.Medium` |
|||
- `AbpFormControlSize.Large` |
|||
* `openButton`: Um botão para abrir o seletor de data será adicionado quando for `True`. O valor padrão é `True`. |
|||
* `clearButton`: Um botão para limpar o seletor de data será adicionado quando for `True`. O valor padrão é `True`. |
|||
* `singleOpenAndClearButton`: Mostra os botões de abrir e limpar em um único botão quando for `True`. O valor padrão é `True`. |
|||
* `isUtc`: Converte a data para UTC quando for `True`. O valor padrão é `False`. |
|||
* `isIso`: Converte a data para o formato ISO quando for `True`. O valor padrão é `False`. |
|||
* `visibleDateFormat`: Define o formato de data da entrada. O formato padrão é o formato de data da cultura do usuário. Você precisa fornecer uma convenção de formato de data JavaScript. Por exemplo: `YYYY-MM-DDTHH:MM:SSZ`. |
|||
* `inputDateFormat`: Define o formato de data do input oculto para compatibilidade com o backend. O formato padrão é `YYYY-MM-DD`. Você precisa fornecer uma convenção de formato de data JavaScript. Por exemplo: `YYYY-MM-DDTHH:MM:SSZ`. |
|||
* `dateSeparator`: Define um caractere para separar as datas de início e término. O valor padrão é `-`. |
|||
* `startDateName`: Define o nome do input de data de início oculto. |
|||
* `endDateName`: Define o nome do input de data de término oculto. |
|||
* `dateName`: Define o nome do input de data oculto. |
|||
* Outras [opções de datepicker](https://www.daterangepicker.com/#options). Por exemplo: `startDate: "2020-01-01"`. |
|||
@ -0,0 +1,273 @@ |
|||
# Grids |
|||
|
|||
## Introdução |
|||
|
|||
Abp tag helpers para o sistema de grid baseado no bootstrap. |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração [grids demo page](https://bootstrap-taghelpers.abp.io/Components/Grids) para ver em ação. |
|||
|
|||
### Dimensionamento |
|||
|
|||
**Largura igual:** Cria colunas com largura igual. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-container> |
|||
<abp-row> |
|||
<abp-column abp-border="Info">1 de 2</abp-column> |
|||
<abp-column abp-border="Danger">2 de 2</abp-column> |
|||
</abp-row> |
|||
<abp-row> |
|||
<abp-column abp-border="Primary">1 de 3</abp-column> |
|||
<abp-column abp-border="Secondary">2 de 3</abp-column> |
|||
<abp-column abp-border="Dark">3 de 3</abp-column> |
|||
</abp-row> |
|||
</abp-container> |
|||
```` |
|||
|
|||
**Quebra de coluna:** `abp-column-breaker` é usado para quebrar a largura automática de colocação da linha atual e iniciar em uma nova linha em seguida. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-container> |
|||
<abp-row> |
|||
<abp-column>coluna</abp-column> |
|||
<abp-column>coluna</abp-column> |
|||
<abp-column-breaker/> |
|||
<abp-column>coluna</abp-column> |
|||
<abp-column>coluna</abp-column> |
|||
</abp-row> |
|||
</abp-container> |
|||
```` |
|||
|
|||
**Definindo a largura de uma coluna:** o atributo size é usado para definir a largura de uma coluna específica. |
|||
|
|||
Exemplo: |
|||
|
|||
```xml |
|||
<abp-container> |
|||
<abp-row> |
|||
<abp-column>1 de 3</abp-column> |
|||
<abp-column size="_6">2 de 3 (mais larga)</abp-column> |
|||
<abp-column>3 de 3</abp-column> |
|||
</abp-row> |
|||
<abp-row> |
|||
<abp-column>1 de 3</abp-column> |
|||
<abp-column size="_5">2 de 3 (mais larga)</abp-column> |
|||
<abp-column>3 de 3</abp-column> |
|||
</abp-row> |
|||
</abp-container> |
|||
``` |
|||
|
|||
**Conteúdo de largura variável:** Coluna de redimensionamento automático com base no conteúdo. |
|||
|
|||
```xml |
|||
<abp-container> |
|||
<abp-row h-align="Center"> |
|||
<abp-column size-lg="_2" abp-border="Info">1 de 3</abp-column> |
|||
<abp-column size-md="Auto" abp-border="Danger">Contrary to popular belief, Lorem Ipsum is not simply random text.</abp-column> |
|||
<abp-column size-lg="_2" abp-border="Warning">3 de 3</abp-column> |
|||
</abp-row> |
|||
<abp-row> |
|||
<abp-column>1 de 3</abp-column> |
|||
<abp-column size-md="Auto">Conteúdo de largura variável</abp-column> |
|||
<abp-column size-lg="_2">3 de 3</abp-column> |
|||
</abp-row> |
|||
</abp-container> |
|||
``` |
|||
|
|||
### Classes Responsivas |
|||
|
|||
As classes responsivas podem ser usadas de forma fortemente tipada dentro das tags abp. |
|||
|
|||
```xml |
|||
<abp-row> |
|||
<abp-column size-sm="_8">col-sm-8</abp-column> |
|||
<abp-column size-sm="_4">col-sm-4</abp-column> |
|||
</abp-row> |
|||
<abp-row> |
|||
<abp-column size-sm="_">col-sm</abp-column> |
|||
<abp-column size-sm="_">col-sm</abp-column> |
|||
<abp-column size-sm="_">col-sm</abp-column> |
|||
<abp-column size-sm="_">col-sm</abp-column> |
|||
</abp-row> |
|||
<!-- Empilhe as colunas em dispositivos móveis, tornando uma em largura total e a outra em meia largura --> |
|||
<abp-row> |
|||
<abp-column size="_12" size-md="_8">.col-12 .col-md-8</abp-column> |
|||
<abp-column size="_6" size-md="_4">.col-6 .col-md-4</abp-column> |
|||
</abp-row> |
|||
|
|||
<!-- As colunas começam com 50% de largura em dispositivos móveis e aumentam para 33,3% de largura em desktop --> |
|||
<abp-row> |
|||
<abp-column size="_6" size-md="_4">.col-6 .col-md-4</abp-column> |
|||
<abp-column size="_6" size-md="_4">.col-6 .col-md-4</abp-column> |
|||
<abp-column size="_6" size-md="_4">.col-6 .col-md-4</abp-column> |
|||
</abp-row> |
|||
|
|||
<!-- As colunas têm sempre 50% de largura, em dispositivos móveis e desktop --> |
|||
<abp-row> |
|||
<abp-column size="_6">.col-6</abp-column> |
|||
<abp-column size="_6">.col-6</abp-column> |
|||
</abp-row> |
|||
``` |
|||
|
|||
### Alinhamento |
|||
|
|||
Os alinhamentos de coluna podem ser feitos de forma fortemente tipada nas tags abp, tanto vertical quanto horizontalmente. |
|||
|
|||
**Alinhamento vertical**: o valor do atributo `v-align` é usado para alinhar as colunas verticalmente. |
|||
|
|||
Exemplo: |
|||
|
|||
```xml |
|||
<abp-container> |
|||
<abp-row v-align="Start"> |
|||
<abp-column>coluna</abp-column> |
|||
<abp-column>coluna</abp-column> |
|||
<abp-column>coluna</abp-column> |
|||
</abp-row> |
|||
<abp-row v-align="Center"> |
|||
<abp-column>coluna</abp-column> |
|||
<abp-column>coluna</abp-column> |
|||
<abp-column>coluna</abp-column> |
|||
</abp-row> |
|||
<abp-row v-align="End"> |
|||
<abp-column>coluna</abp-column> |
|||
<abp-column>coluna</abp-column> |
|||
<abp-column>coluna</abp-column> |
|||
</abp-row> |
|||
</abp-container> |
|||
``` |
|||
|
|||
**Alinhamento horizontal**: o valor do atributo `h-align` é usado para alinhar as colunas horizontalmente. |
|||
|
|||
Exemplo: |
|||
|
|||
```xml |
|||
<abp-container> |
|||
<abp-row h-align="Start"> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
</abp-row> |
|||
<abp-row h-align="Center"> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
</abp-row> |
|||
<abp-row h-align="End"> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
</abp-row> |
|||
<abp-row h-align="Around"> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
</abp-row> |
|||
<abp-row h-align="Between"> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
</abp-row> |
|||
</abp-container> |
|||
``` |
|||
|
|||
**Sem margens**: as margens entre as colunas nas classes de grade predefinidas podem ser removidas com `gutters="false"`. Isso remove as margens negativas de `abp-row` e o preenchimento horizontal de todas as colunas filhas imediatas. |
|||
|
|||
Exemplo: |
|||
|
|||
```xml |
|||
<abp-row gutters="false"> |
|||
<abp-column size="_8">Uma de duas colunas</abp-column> |
|||
<abp-column size="_4">Uma de duas colunas</abp-column> |
|||
</abp-row> |
|||
``` |
|||
|
|||
**Quebra de coluna**: se mais de 12 colunas forem colocadas em uma única linha, cada grupo de colunas extras será, como uma unidade, quebrado em uma nova linha. |
|||
|
|||
Exemplo: |
|||
|
|||
```xml |
|||
<abp-row> |
|||
<abp-column size="_9">.col-9</abp-column> |
|||
<abp-column size="_4">.col-4<br>Since 9 + 4 = 13 > 12, this 4-column-wide div gets wrapped onto a new line as one contiguous unit.</abp-column> |
|||
<abp-column size="_6">.col-6<br>Subsequent columns continue along the new line.s</abp-column> |
|||
</abp-row> |
|||
``` |
|||
|
|||
### Reordenamento |
|||
|
|||
**Classes de ordem**: o atributo `order` é usado para controlar a ordem visual do conteúdo. |
|||
|
|||
Exemplo: |
|||
|
|||
```xml |
|||
<abp-container> |
|||
<abp-row> |
|||
<abp-column order="_12">Primeiro, mas último</abp-column> |
|||
<abp-column>Segundo, mas não ordenado</abp-column> |
|||
<abp-column order="_6">Terceiro, mas segundo</abp-column> |
|||
</abp-row> |
|||
</abp-container> |
|||
``` |
|||
|
|||
**Deslocamento de colunas**: o atributo `offset` é usado para definir o deslocamento das colunas da grade. |
|||
|
|||
Exemplo: |
|||
|
|||
```xml |
|||
<abp-container> |
|||
<abp-row> |
|||
<abp-column size-md="_4">.col-md-4</abp-column> |
|||
<abp-column size-md="_4" offset-md="_4">.col-md-4 .offset-md-4</abp-column> |
|||
</abp-row> |
|||
<abp-row> |
|||
<abp-column size-md="_3" offset-md="_3">.col-md-3 .offset-md-3</abp-column> |
|||
<abp-column size-md="_3" offset-md="_3">.col-md-3 .offset-md-3</abp-column> |
|||
</abp-row> |
|||
<abp-row> |
|||
<abp-column size-md="_6" offset-md="_3">.col-md-6 .offset-md-3</abp-column> |
|||
</abp-row> |
|||
<abp-row> |
|||
<abp-column size-sm="_5" size-md="_6">.col-sm-5 .col-md-6</abp-column> |
|||
<abp-column size-sm="_5" offset-sm="_2" size-md="_6" offset-md="_">.col-sm-5 .offset-sm-2 .col-md-6 .offset-md-0</abp-column> |
|||
</abp-row> |
|||
<abp-row> |
|||
<abp-column size-sm="_6" size-md="_5" size-lg="_6">col-sm-6 .col-md-5 .col-lg-6</abp-column> |
|||
<abp-column size-sm="_6" size-md="_5" offset-md="_2" size-lg="_6" offset-lg="_">.col-sm-6 .col-md-5 .offset-md-2 .col-lg-6 .offset-lg-0</abp-column> |
|||
</abp-row> |
|||
</abp-container> |
|||
``` |
|||
|
|||
## Atributos de abp-row |
|||
|
|||
- **v-align:** Um valor que indica o posicionamento vertical das colunas contidas. Deve ser um dos seguintes valores: |
|||
* `Default` (valor padrão) |
|||
* `Start` |
|||
* `Center` |
|||
* `End` |
|||
|
|||
- **h-align**: Um valor que indica o posicionamento horizontal das colunas contidas. Deve ser um dos seguintes valores: |
|||
* `Default` (valor padrão) |
|||
* `Start` |
|||
* `Center` |
|||
* `Around` |
|||
* `Between` |
|||
* `End` |
|||
- **gutter**: Um valor que indica se as margens negativas e o preenchimento horizontal serão removidos de todas as colunas filhas. Atuará como valor `true` se esse atributo não for definido. Deve ser um dos seguintes valores: |
|||
* `true` |
|||
* `false` |
|||
|
|||
## Atributos de abp-column |
|||
|
|||
- **size:** Um valor que indica a largura da coluna de `_`, `Undefined`, `_1`..`_12`, `Auto`. Ou pode ser usado com valores predefinidos como: |
|||
- `size-sm` |
|||
- `size-md` |
|||
- `size-lg` |
|||
- `size-xl` |
|||
- **order**: Um valor que indica a ordem da coluna de `Undefined`, `_1`..`_12`, `First` e `Last`. |
|||
- **offset:** Um valor que indica o deslocamento da coluna de `_`, `Undefined`, `_1`..`_12`, `Auto`. Ou pode ser usado com valores predefinidos como: |
|||
- `offset-sm` |
|||
- `offset-md` |
|||
- `offset-lg` |
|||
- `offset-xl` |
|||
@ -0,0 +1,45 @@ |
|||
# ABP Tag Helpers |
|||
|
|||
O ABP Framework define um conjunto de **componentes de tag helper** para simplificar o desenvolvimento da interface do usuário para aplicativos ASP.NET Core (MVC / Razor Pages). |
|||
|
|||
## Wrappers de Componentes Bootstrap |
|||
|
|||
A maioria dos tag helpers são wrappers do [Bootstrap](https://getbootstrap.com/) (v5+). Codificar o Bootstrap não é tão fácil, não é tão seguro em termos de tipo e contém muitas tags HTML repetitivas. Os ABP Tag Helpers tornam isso mais **fácil** e **seguro em termos de tipo**. |
|||
|
|||
Não temos como objetivo envolver 100% dos componentes do Bootstrap. Ainda é possível escrever **código de estilo nativo do Bootstrap** (na verdade, os tag helpers geram código nativo do Bootstrap no final), mas sugerimos usar os tag helpers sempre que possível. |
|||
|
|||
O ABP Framework também adiciona alguns **recursos úteis** aos componentes padrão do Bootstrap. |
|||
|
|||
Aqui está a lista de componentes que são envolvidos pelo ABP Framework: |
|||
|
|||
* [Alertas](Alerts.md) |
|||
* [Badges](Badges.md) |
|||
* [Blockquote](Blockquote.md) |
|||
* [Bordas](Borders.md) |
|||
* [Breadcrumb](Breadcrumbs.md) |
|||
* [Botões](Buttons.md) |
|||
* [Cards](Cards.md) |
|||
* [Carousel](Carousel.md) |
|||
* [Collapse](Collapse.md) |
|||
* [Dropdowns](Dropdowns.md) |
|||
* [Figuras](Figure.md) |
|||
* [Grids](Grids.md) |
|||
* [List Groups](List-Groups.md) |
|||
* [Modals](Modals.md) |
|||
* [Navegação](Navs.md) |
|||
* [Paginator](Paginator.md) |
|||
* [Popovers](Popovers.md) |
|||
* [Barras de Progresso](Progress-Bars.md) |
|||
* [Tabelas](Tables.md) |
|||
* [Abas](Tabs.md) |
|||
* [Tooltips](Tooltips.md) |
|||
|
|||
> Até que todos os tag helpers sejam documentados, você pode visitar https://bootstrap-taghelpers.abp.io/ para vê-los com exemplos ao vivo. |
|||
|
|||
## Elementos de Formulário |
|||
|
|||
Os **Abp Tag Helpers** adicionam novos recursos aos **Tag Helpers de entrada e seleção do Asp.Net Core MVC** padrão e os envolvem com controles de formulário do **Bootstrap**. Consulte a documentação de [Elementos de Formulário](Form-elements.md). |
|||
|
|||
## Formulários Dinâmicos |
|||
|
|||
Os **Abp Tag Helpers** oferecem uma maneira fácil de construir formulários completos do **Bootstrap**. Consulte a documentação de [Formulários Dinâmicos](Dynamic-Forms.md). |
|||
@ -0,0 +1,76 @@ |
|||
# Listas de Grupos |
|||
|
|||
## Introdução |
|||
|
|||
`abp-list-group` é o contêiner principal para o conteúdo do grupo de listas. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-list-group> |
|||
<abp-list-group-item>Cras justo odio</abp-list-group-item> |
|||
<abp-list-group-item>Dapibus ac facilisis in</abp-list-group-item> |
|||
<abp-list-group-item>Morbi leo risus</abp-list-group-item> |
|||
<abp-list-group-item>Vestibulum at eros</abp-list-group-item> |
|||
</abp-list-group> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a [página de demonstração de grupos de listas](https://bootstrap-taghelpers.abp.io/Components/ListGroup) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### flush |
|||
|
|||
Um valor indica que os itens `abp-list-group` devem remover algumas bordas e cantos arredondados para renderizar os itens do grupo de listas de ponta a ponta em um contêiner pai. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### active |
|||
|
|||
Um valor indica se um `abp-list-group-item` deve estar ativo. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### disabled |
|||
|
|||
Um valor indica se um `abp-list-group-item` deve estar desativado. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### href |
|||
|
|||
Um valor indica se um `abp-list-group-item` possui um link. Deve ser um valor de link de string. |
|||
|
|||
### type |
|||
|
|||
Um valor indica uma classe de estilo `abp-list-group-item` com um plano de fundo e cor com estado. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` (valor padrão) |
|||
* `Primary` |
|||
* `Secondary` |
|||
* `Success` |
|||
* `Danger` |
|||
* `Warning` |
|||
* `Info` |
|||
* `Light` |
|||
* `Dark` |
|||
* `Link` |
|||
|
|||
### Conteúdo adicional |
|||
|
|||
`abp-list-group-item` também pode conter elementos HTML adicionais, como spans. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-list-group> |
|||
<abp-list-group-item>Cras justo odio <span abp-badge-pill="Primary">14</span></abp-list-group-item> |
|||
<abp-list-group-item>Dapibus ac facilisis in <span abp-badge-pill="Primary">2</span></abp-list-group-item> |
|||
<abp-list-group-item>Morbi leo risus <span abp-badge-pill="Primary">1</span></abp-list-group-item> |
|||
</abp-list-group> |
|||
```` |
|||
@ -0,0 +1,88 @@ |
|||
# Modais |
|||
|
|||
> Este documento explica os detalhes do `abp-modal` Tag Helper, que simplifica a construção da marcação HTML para uma caixa de diálogo modal. Leia [essa documentação](../Modals.md) para aprender como trabalhar com modais. |
|||
|
|||
## Introdução |
|||
|
|||
`abp-modal` é um elemento principal para criar um modal. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-button button-type="Primary" data-toggle="modal" data-target="#myModal">Abrir modal</abp-button> |
|||
|
|||
<abp-modal centered="true" scrollable="true" size="Large" id="myModal"> |
|||
<abp-modal-header title="Título do modal"></abp-modal-header> |
|||
<abp-modal-body> |
|||
Uau, você está lendo este texto em um modal! |
|||
</abp-modal-body> |
|||
<abp-modal-footer buttons="Fechar"></abp-modal-footer> |
|||
</abp-modal> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a [página de demonstração de modais](https://bootstrap-taghelpers.abp.io/Components/Modals) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### centered |
|||
|
|||
Um valor que indica o posicionamento do modal. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### Scrollable |
|||
|
|||
Um valor que indica a rolagem do modal. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### size |
|||
|
|||
Um valor que indica o tamanho do modal. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` (valor padrão) |
|||
* `Small` |
|||
* `Large` |
|||
* `ExtraLarge` |
|||
|
|||
### static |
|||
|
|||
Um valor que indica se o modal será estático. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### Conteúdo adicional |
|||
|
|||
`abp-modal-footer` pode ter vários botões com opção de alinhamento. |
|||
|
|||
Adicione `@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal` à sua página. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-button button-type="Primary" data-toggle="modal" data-target="#myModal">Abrir modal</abp-button> |
|||
|
|||
<abp-modal centered="true" size="Large" id="myModal" static="true"> |
|||
<abp-modal-header title="Título do modal"></abp-modal-header> |
|||
<abp-modal-body> |
|||
Uau, você está lendo este texto em um modal! |
|||
</abp-modal-body> |
|||
<abp-modal-footer buttons="@(AbpModalButtons.Save|AbpModalButtons.Close)" button-alignment="Between"></abp-modal-footer> |
|||
</abp-modal> |
|||
```` |
|||
|
|||
### button-alignment |
|||
|
|||
Um valor que indica o posicionamento dos botões do rodapé do modal. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` (valor padrão) |
|||
* `Start` |
|||
* `Center` |
|||
* `Around` |
|||
* `Between` |
|||
* `End` |
|||
@ -0,0 +1,114 @@ |
|||
# Navs |
|||
|
|||
## Introdução |
|||
|
|||
`abp-nav` é o componente básico de tag helper derivado do elemento de navegação do bootstrap. |
|||
|
|||
Uso básico: |
|||
|
|||
````html |
|||
<abp-nav nav-style="Pill" align="Center"> |
|||
<abp-nav-item> |
|||
<a abp-nav-link active="true" href="#">Ativo</a> |
|||
</abp-nav-item> |
|||
<abp-nav-item> |
|||
<a abp-nav-link href="#">Link de navegação mais longo</a> |
|||
</abp-nav-item> |
|||
<abp-nav-item> |
|||
<a abp-nav-link href="#">link</a> |
|||
</abp-nav-item> |
|||
<abp-nav-item> |
|||
<a abp-nav-link disabled="true" href="#">desativado</a> |
|||
</abp-nav-item> |
|||
</abp-nav> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a [página de demonstração de navegação](https://bootstrap-taghelpers.abp.io/Components/Navs) para vê-la em ação. |
|||
|
|||
## Atributos do abp-nav |
|||
|
|||
- **nav-style**: O valor indica o posicionamento e estilo dos itens contidos. Deve ser um dos seguintes valores: |
|||
* `Default` (valor padrão) |
|||
* `Vertical` |
|||
* `Pill` |
|||
* `PillVertical` |
|||
- **align:** O valor indica o alinhamento dos itens contidos: |
|||
* `Default` (valor padrão) |
|||
* `Start` |
|||
* `Center` |
|||
* `End` |
|||
|
|||
### Atributos do abp-nav-bar |
|||
|
|||
- **nav-style**: O valor indica o layout de cores da barra de navegação base. Deve ser um dos seguintes valores: |
|||
* `Default` (valor padrão) |
|||
* `Dark` |
|||
* `Light` |
|||
* `Dark_Primary` |
|||
* `Dark_Secondary` |
|||
* `Dark_Success` |
|||
* `Dark_Danger` |
|||
* `Dark_Warning` |
|||
* `Dark_Info` |
|||
* `Dark_Dark` |
|||
* `Dark_Link` |
|||
* `Light_Primary` |
|||
* `Light_Secondary` |
|||
* `Light_Success` |
|||
* `Light_Danger` |
|||
* `Light_Warning` |
|||
* `Light_Info` |
|||
* `Light_Dark` |
|||
* `Light_Link` |
|||
- **size:** O valor indica o tamanho da barra de navegação base. Deve ser um dos seguintes valores: |
|||
* `Default` (valor padrão) |
|||
* `Sm` |
|||
* `Md` |
|||
* `Lg` |
|||
* `Xl` |
|||
|
|||
### Atributos do abp-nav-item |
|||
|
|||
**dropdown**: Um valor que define o item de navegação como um menu suspenso, se fornecido. Pode ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
Exemplo: |
|||
|
|||
````html |
|||
<abp-nav-bar size="Lg" navbar-style="Dark_Warning"> |
|||
<a abp-navbar-brand href="#">Navbar</a> |
|||
<abp-navbar-toggle> |
|||
<abp-navbar-nav> |
|||
<abp-nav-item active="true"> |
|||
<a abp-nav-link href="#">Início <span class="sr-only">(atual)</span></a> |
|||
</abp-nav-item> |
|||
<abp-nav-item> |
|||
<a abp-nav-link href="#">Link</a> |
|||
</abp-nav-item> |
|||
<abp-nav-item dropdown="true"> |
|||
<abp-dropdown> |
|||
<abp-dropdown-button nav-link="true" text="Dropdown" /> |
|||
<abp-dropdown-menu> |
|||
<abp-dropdown-header>Cabeçalho do menu suspenso</abp-dropdown-header> |
|||
<abp-dropdown-item href="#" active="true">Ação</abp-dropdown-item> |
|||
<abp-dropdown-item href="#" disabled="true">Outra ação desativada</abp-dropdown-item> |
|||
<abp-dropdown-item href="#">Algo mais aqui</abp-dropdown-item> |
|||
<abp-dropdown-divider /> |
|||
<abp-dropdown-item href="#">Link separado</abp-dropdown-item> |
|||
</abp-dropdown-menu> |
|||
</abp-dropdown> |
|||
</abp-nav-item> |
|||
<abp-nav-item> |
|||
<a abp-nav-link disabled="true" href="#">Desativado</a> |
|||
</abp-nav-item> |
|||
</abp-navbar-nav> |
|||
<span abp-navbar-text> |
|||
Texto de exemplo |
|||
</span> |
|||
</abp-navbar-toggle> |
|||
</abp-nav-bar> |
|||
``` |
|||
@ -0,0 +1,57 @@ |
|||
# Paginador |
|||
|
|||
## Introdução |
|||
|
|||
`abp-paginator` é a tag abp para paginação. Requer um modelo do tipo `Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination.PagerModel`. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-paginator model="Model.PagerModel" show-info="true"></abp-paginator> |
|||
```` |
|||
|
|||
Modelo: |
|||
|
|||
````csharp |
|||
using Microsoft.AspNetCore.Mvc.RazorPages; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components |
|||
{ |
|||
public class PaginatorModel : PageModel |
|||
{ |
|||
public PagerModel PagerModel { get; set; } |
|||
|
|||
public void OnGet(int currentPage, string sort) |
|||
{ |
|||
PagerModel = new PagerModel(100, 10, currentPage, 10, "/Components/Paginator", sort); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
|
|||
|
|||
## Demonstração |
|||
|
|||
Veja a [página de demonstração do paginador](https://bootstrap-taghelpers.abp.io/Components/Paginator) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### model |
|||
|
|||
O modelo do tipo `Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination.PagerModel` pode ser inicializado com os seguintes dados: |
|||
|
|||
* `totalCount` |
|||
* `shownItemsCount` |
|||
* `currentPage` |
|||
* `pageSize` |
|||
* `pageUrl` |
|||
* `sort` (padrão nulo) |
|||
|
|||
### show-info |
|||
|
|||
Um valor que indica se uma informação extra sobre o início, fim e total de registros será exibida. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
@ -0,0 +1,40 @@ |
|||
# Popovers |
|||
|
|||
## Introdução |
|||
|
|||
`abp-popover` é a tag abp para mensagens de popover. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-button abp-popover="Oi, eu sou o conteúdo do popover!"> |
|||
Popover Padrão |
|||
</abp-button> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração de [popovers](https://bootstrap-taghelpers.abp.io/Components/Popovers) para vê-lo em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### disabled |
|||
|
|||
Um valor que indica se o elemento deve ser desabilitado para interação. Se esse valor for definido como `true`, o atributo `dismissable` será ignorado. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### dismissable |
|||
|
|||
Um valor que indica se os popovers devem ser fechados no próximo clique do usuário em um elemento diferente do elemento de ativação. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### hoverable |
|||
|
|||
Um valor que indica se o conteúdo do popover será exibido ao passar o mouse sobre ele. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
@ -0,0 +1,68 @@ |
|||
# Barras de Progresso |
|||
|
|||
## Introdução |
|||
|
|||
`abp-progress-bar` é a tag abp para o status da barra de progresso. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-progress-bar value="70" /> |
|||
|
|||
<abp-progress-bar type="Warning" value="25"> %25 </abp-progress-bar> |
|||
|
|||
<abp-progress-bar type="Success" value="40" strip="true"/> |
|||
|
|||
<abp-progress-bar type="Dark" value="10" min-value="5" max-value="15" strip="true"> %50 </abp-progress-bar> |
|||
|
|||
<abp-progress-group> |
|||
<abp-progress-part type="Success" value="25"/> |
|||
<abp-progress-part type="Danger" value="10" strip="true"> %10 </abp-progress-part> |
|||
<abp-progress-part type="Primary" value="50" animation="true" strip="true" /> |
|||
</abp-progress-group> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração das [barras de progresso](https://bootstrap-taghelpers.abp.io/Components/Progressbars) para vê-las em ação. |
|||
|
|||
## Atributos |
|||
|
|||
### value |
|||
|
|||
Um valor que indica o progresso atual da barra. |
|||
|
|||
### type |
|||
|
|||
Um valor que indica a cor de fundo da barra de progresso. Deve ser um dos seguintes valores: |
|||
|
|||
* `Default` (valor padrão) |
|||
* `Secondary` |
|||
* `Success` |
|||
* `Danger` |
|||
* `Warning` |
|||
* `Info` |
|||
* `Light` |
|||
* `Dark` |
|||
|
|||
### min-value |
|||
|
|||
Valor mínimo da barra de progresso. O padrão é 0. |
|||
|
|||
### max-value |
|||
|
|||
Valor máximo da barra de progresso. O padrão é 100. |
|||
|
|||
### strip |
|||
|
|||
Um valor que indica se o estilo de fundo da barra de progresso é listrado. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
|
|||
### animation |
|||
|
|||
Um valor que indica se o estilo de fundo listrado da barra de progresso é animado. Deve ser um dos seguintes valores: |
|||
|
|||
* `false` (valor padrão) |
|||
* `true` |
|||
@ -0,0 +1,61 @@ |
|||
# Tabelas |
|||
|
|||
## Introdução |
|||
|
|||
`abp-table` é o componente básico de tag para tabelas no abp. |
|||
|
|||
Uso básico: |
|||
|
|||
````html |
|||
<abp-table hoverable-rows="true" responsive-sm="true"> |
|||
<thead> |
|||
<tr> |
|||
<th scope="Column">#</th> |
|||
<th scope="Column">Primeiro</th> |
|||
<th scope="Column">Último</th> |
|||
<th scope="Column">Identificador</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr> |
|||
<th scope="Row">1</th> |
|||
<td>Mark</td> |
|||
<td>Otto</td> |
|||
<td table-style="Danger">mdo</td> |
|||
</tr> |
|||
<tr table-style="Warning"> |
|||
<th scope="Row">2</th> |
|||
<td>Jacob</td> |
|||
<td>Thornton</td> |
|||
<td>fat</td> |
|||
</tr> |
|||
<tr> |
|||
<th scope="Row">3</th> |
|||
<td table-style="Success">Larry</td> |
|||
<td>the Bird</td> |
|||
<td>twitter</td> |
|||
</tr> |
|||
</tbody> |
|||
</abp-table> |
|||
```` |
|||
|
|||
|
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração de [tabelas](https://bootstrap-taghelpers.abp.io/Components/Tables) para vê-la em ação. |
|||
|
|||
## Atributos do abp-table |
|||
|
|||
- **responsive**: Usado para criar tabelas responsivas até um determinado ponto de interrupção. Veja [específico do ponto de interrupção](https://getbootstrap.com/docs/4.1/content/tables/#breakpoint-specific) para mais informações. |
|||
- **responsive-sm**: Se não for definido como false, define a responsividade da tabela para dispositivos de tela pequena. |
|||
- **responsive-md**: Se não for definido como false, define a responsividade da tabela para dispositivos de tela média. |
|||
- **responsive-lg**: Se não for definido como false, define a responsividade da tabela para dispositivos de tela grande. |
|||
- **responsive-xl**: Se não for definido como false, define a responsividade da tabela para dispositivos de tela extra grande. |
|||
- **dark-theme**: Se definido como true, define o tema de cor da tabela como escuro. |
|||
- **striped-rows**: Se definido como true, adiciona listras zebradas às linhas da tabela. |
|||
- **hoverable-rows**: Se definido como true, adiciona estado de hover às linhas da tabela. |
|||
- **border-style**: Define o estilo da borda da tabela. Deve ser um dos seguintes valores: |
|||
- `Default` (padrão) |
|||
- `Bordered` |
|||
- `Borderless` |
|||
@ -0,0 +1,91 @@ |
|||
# Abas |
|||
|
|||
## Introdução |
|||
|
|||
`abp-tab` é o contêiner básico de conteúdo de navegação por abas derivado do elemento de aba do Bootstrap. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-tabs> |
|||
<abp-tab title="Home"> |
|||
Conteúdo_Início |
|||
</abp-tab> |
|||
<abp-tab-link title="Link" href="#" /> |
|||
<abp-tab title="perfil"> |
|||
Conteúdo_Perfil |
|||
</abp-tab> |
|||
<abp-tab-dropdown title="Contato" name="DropdownContato"> |
|||
<abp-tab title="Contato 1" parent-dropdown-name="DropdownContato"> |
|||
Conteúdo_1_Conteúdo |
|||
</abp-tab> |
|||
<abp-tab title="Contato 2" parent-dropdown-name="DropdownContato"> |
|||
Conteúdo_2_Conteúdo |
|||
</abp-tab> |
|||
</abp-tab-dropdown> |
|||
</abp-tabs> |
|||
```` |
|||
|
|||
## Demonstração |
|||
|
|||
Veja a [página de demonstração de abas](https://bootstrap-taghelpers.abp.io/Components/Tabs) para vê-la em ação. |
|||
|
|||
## Atributos do abp-tab |
|||
|
|||
- **title**: Define o texto do menu da aba. |
|||
- **name:** Define o atributo "id" dos elementos gerados. O valor padrão é um Guid. Não é necessário, a menos que as abas sejam alteradas ou modificadas com Jquery. |
|||
- **active**: Define a aba ativa. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-tabs name="IdDaAba"> |
|||
<abp-tab name="nav-inicio" title="Home"> |
|||
Conteúdo_Início |
|||
</abp-tab> |
|||
<abp-tab name="nav-perfil" active="true" title="perfil"> |
|||
Conteúdo_Perfil |
|||
</abp-tab> |
|||
<abp-tab name="nav-contato" title="Contato"> |
|||
Conteúdo_Contato |
|||
</abp-tab> |
|||
</abp-tabs> |
|||
```` |
|||
|
|||
### Pílulas |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-tabs tab-style="Pill"> |
|||
<abp-tab title="Home"> |
|||
Conteúdo_Início |
|||
</abp-tab> |
|||
<abp-tab title="perfil"> |
|||
Conteúdo_Perfil |
|||
</abp-tab> |
|||
<abp-tab title="Contato"> |
|||
Conteúdo_Contato |
|||
</abp-tab> |
|||
</abp-tabs> |
|||
```` |
|||
|
|||
### Vertical |
|||
|
|||
**vertical-header-size**: Define a largura da coluna dos cabeçalhos das abas. |
|||
|
|||
Exemplo: |
|||
|
|||
````xml |
|||
<abp-tabs tab-style="PillVertical" vertical-header-size="_2" > |
|||
<abp-tab active="true" title="Home"> |
|||
Conteúdo_Início |
|||
</abp-tab> |
|||
<abp-tab title="perfil"> |
|||
Conteúdo_Perfil |
|||
</abp-tab> |
|||
<abp-tab title="Contato"> |
|||
Conteúdo_Contato |
|||
</abp-tab> |
|||
</abp-tabs> |
|||
```` |
|||
@ -0,0 +1,35 @@ |
|||
# Dicas de Ferramentas |
|||
|
|||
## Introdução |
|||
|
|||
`abp-tooltip` é a tag abp para dicas de ferramentas. |
|||
|
|||
Uso básico: |
|||
|
|||
````xml |
|||
<abp-button abp-tooltip="Dica de Ferramenta"> |
|||
Dica de Ferramenta Padrão |
|||
</abp-button> |
|||
|
|||
<abp-button abp-tooltip-top="Dica de Ferramenta"> |
|||
Dica de Ferramenta no topo |
|||
</abp-button> |
|||
|
|||
<abp-button abp-tooltip-right="Dica de Ferramenta"> |
|||
Dica de Ferramenta à direita |
|||
</abp-button> |
|||
|
|||
<abp-button abp-tooltip-bottom="Dica de Ferramenta"> |
|||
Dica de Ferramenta na parte inferior |
|||
</abp-button> |
|||
|
|||
<abp-button disabled="true" abp-tooltip="Dica de Ferramenta"> |
|||
Dica de Ferramenta do botão desativado |
|||
</abp-button> |
|||
```` |
|||
|
|||
|
|||
|
|||
## Demonstração |
|||
|
|||
Veja a página de demonstração de [dicas de ferramentas](https://bootstrap-taghelpers.abp.io/Components/Tooltips) para vê-la em ação. |
|||
@ -0,0 +1,207 @@ |
|||
# ASP.NET Core MVC / Razor Pages: Testando |
|||
|
|||
> Você pode seguir a documentação de Testes de Integração do ASP.NET Core (ASP.NET Core Integration Tests) para aprender detalhes sobre os testes de integração do ASP.NET Core. Este documento explica a infraestrutura de teste adicional fornecida pelo ABP Framework. |
|||
|
|||
## O Modelo de Inicialização do Aplicativo |
|||
|
|||
O Modelo de Inicialização do Aplicativo contém o projeto `.Web` que contém as visualizações/páginas/componentes de interface do usuário do aplicativo e um projeto `.Web.Tests` para testá-los. |
|||
|
|||
 |
|||
|
|||
## Testando as Páginas Razor |
|||
|
|||
Suponha que você tenha criado uma Página Razor chamada `Issues.cshtml` com o seguinte conteúdo; |
|||
|
|||
**Issues.cshtml.cs** |
|||
|
|||
````csharp |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc.RazorPages; |
|||
using MyProject.Issues; |
|||
|
|||
namespace MyProject.Web.Pages |
|||
{ |
|||
public class IssuesModel : PageModel |
|||
{ |
|||
public List<IssueDto> Issues { get; set; } |
|||
|
|||
private readonly IIssueAppService _issueAppService; |
|||
|
|||
public IssuesModel(IIssueAppService issueAppService) |
|||
{ |
|||
_issueAppService = issueAppService; |
|||
} |
|||
|
|||
public async Task OnGetAsync() |
|||
{ |
|||
Issues = await _issueAppService.GetListAsync(); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
**Issues.cshtml** |
|||
|
|||
````html |
|||
@page |
|||
@model MyProject.Web.Pages.IssuesModel |
|||
<h2>Lista de Problemas</h2> |
|||
<table id="IssueTable" class="table"> |
|||
<thead> |
|||
<tr> |
|||
<th>Problema</th> |
|||
<th>Fechado?</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
@foreach (var issue in Model.Issues) |
|||
{ |
|||
<tr> |
|||
<td>@issue.Title</td> |
|||
<td> |
|||
@if (issue.IsClosed) |
|||
{ |
|||
<span>Fechado</span> |
|||
} |
|||
else |
|||
{ |
|||
<span>Aberto</span> |
|||
} |
|||
</td> |
|||
</tr> |
|||
} |
|||
</tbody> |
|||
</table> |
|||
```` |
|||
|
|||
Esta página simplesmente cria uma tabela com os problemas: |
|||
|
|||
 |
|||
|
|||
Você pode escrever uma classe de teste dentro do projeto `.Web.Tests` da mesma forma que o exemplo abaixo: |
|||
|
|||
````csharp |
|||
using System.Threading.Tasks; |
|||
using HtmlAgilityPack; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace MyProject.Pages |
|||
{ |
|||
public class Issues_Tests : MyProjectWebTestBase |
|||
{ |
|||
[Fact] |
|||
public async Task Should_Get_Table_Of_Issues() |
|||
{ |
|||
// Agir |
|||
|
|||
var response = await GetResponseAsStringAsync("/Issues"); |
|||
|
|||
// Assert |
|||
|
|||
var htmlDocument = new HtmlDocument(); |
|||
htmlDocument.LoadHtml(response); |
|||
|
|||
var tableElement = htmlDocument.GetElementbyId("IssueTable"); |
|||
tableElement.ShouldNotBeNull(); |
|||
|
|||
var trNodes = tableElement.SelectNodes("//tbody/tr"); |
|||
trNodes.Count.ShouldBeGreaterThan(0); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
`GetResponseAsStringAsync` é um método de atalho que vem da classe base que realiza uma solicitação HTTP GET, verifica se o status HTTP resultante é `200` e retorna a resposta como uma `string`. |
|||
|
|||
> Você pode usar o objeto base `Client` (do tipo `HttpClient`) para realizar qualquer tipo de solicitação ao servidor e ler a resposta você mesmo. `GetResponseAsStringAsync` é apenas um método de atalho. |
|||
|
|||
Este exemplo usa a biblioteca [HtmlAgilityPack](https://html-agility-pack.net/) para analisar o HTML recebido e testar se ele contém a tabela de problemas. |
|||
|
|||
> Este exemplo pressupõe que existam alguns problemas iniciais no banco de dados. Consulte a seção *The Data Seed* do documento de Testes (Testing document) para aprender como inserir dados de teste, para que seus testes possam assumir que alguns dados iniciais estão disponíveis no banco de dados. |
|||
|
|||
## Testando os Controladores |
|||
|
|||
Testar um controlador não é diferente. Basta fazer uma solicitação ao servidor com uma URL adequada, obter a resposta e fazer suas asserções. |
|||
|
|||
### Resultado de Visualização |
|||
|
|||
Se o controlador retornar uma visualização, você pode usar um código semelhante para testar o HTML retornado. Veja o exemplo das Páginas Razor acima. |
|||
|
|||
### Resultado de Objeto |
|||
|
|||
Se o controlador retornar um resultado de objeto, você pode usar o método base `GetResponseAsObjectAsync`. |
|||
|
|||
Suponha que você tenha um controlador definido da seguinte forma: |
|||
|
|||
````csharp |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using MyProject.Issues; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace MyProject.Web.Controllers |
|||
{ |
|||
[Route("api/issues")] |
|||
public class IssueController : AbpController |
|||
{ |
|||
private readonly IIssueAppService _issueAppService; |
|||
|
|||
public IssueController(IIssueAppService issueAppService) |
|||
{ |
|||
_issueAppService = issueAppService; |
|||
} |
|||
|
|||
[HttpGet] |
|||
public async Task<List<IssueDto>> GetAsync() |
|||
{ |
|||
return await _issueAppService.GetListAsync(); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Você pode escrever um código de teste para executar a API e obter o resultado: |
|||
|
|||
````csharp |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using MyProject.Issues; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace MyProject.Pages |
|||
{ |
|||
public class Issues_Tests : MyProjectWebTestBase |
|||
{ |
|||
[Fact] |
|||
public async Task Should_Get_Issues_From_Api() |
|||
{ |
|||
var issues = await GetResponseAsObjectAsync<List<IssueDto>>("/api/issues"); |
|||
|
|||
issues.ShouldNotBeNull(); |
|||
issues.Count.ShouldBeGreaterThan(0); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
## Testando o Código JavaScript |
|||
|
|||
O ABP Framework não fornece nenhuma infraestrutura para testar seu código JavaScript. Você pode usar qualquer estrutura de teste e ferramentas para testar seu código JavaScript. |
|||
|
|||
## A Infraestrutura de Teste |
|||
|
|||
O pacote [Volo.Abp.AspNetCore.TestBase](https://www.nuget.org/packages/Volo.Abp.AspNetCore.TestBase) fornece a infraestrutura de teste que está integrada ao ABP Framework e ao ASP.NET Core. |
|||
|
|||
> O pacote Volo.Abp.AspNetCore.TestBase já está instalado no projeto `.Web.Tests`. |
|||
|
|||
Este pacote fornece a classe base `AbpWebApplicationFactoryIntegratedTest` como a classe base fundamental para derivar as classes de teste. Ela é herdada da classe [WebApplicationFactory](https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests) fornecida pelo ASP.NET Core. |
|||
|
|||
A classe base `MyProjectWebTestBase` usada acima herda da `AbpWebApplicationFactoryIntegratedTest`, então herdamos indiretamente a `AbpWebApplicationFactoryIntegratedTest`. |
|||
|
|||
Veja também |
|||
* [Testes de integração no ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests) |
|||
* [Testes Gerais / Lado do Servidor](../../Testing.md) |
|||
@ -0,0 +1,442 @@ |
|||
# ASP.NET Core MVC / Razor Pages: Tematização de UI |
|||
|
|||
## Introdução |
|||
|
|||
O ABP Framework fornece um sistema completo de **tematização de UI** com os seguintes objetivos: |
|||
|
|||
* Módulos de aplicativos reutilizáveis são desenvolvidos de forma **independente de tema**, para que possam funcionar com qualquer tema de UI. |
|||
* O tema de UI é **decidido pela aplicação final**. |
|||
* O tema é distribuído por meio de pacotes NuGet/NPM, para que seja **facilmente atualizável**. |
|||
* A aplicação final pode **personalizar** o tema selecionado. |
|||
|
|||
Para alcançar esses objetivos, o ABP Framework: |
|||
|
|||
* Determina um conjunto de **bibliotecas base** usadas e adaptadas por todos os temas. Assim, os desenvolvedores de módulos e aplicativos podem depender e usar essas bibliotecas sem depender de um tema específico. |
|||
* Fornece um sistema que consiste em [menus de navegação](../../Navigation-Menu.md), [barras de ferramentas](../../Toolbars.md), [hooks de layout](../../Layout-Hooks.md)... que são implementados por todos os temas. Assim, os módulos e a aplicação contribuem para o layout para compor uma UI de aplicação consistente. |
|||
|
|||
### Temas Atuais |
|||
|
|||
Atualmente, quatro temas são **oficialmente fornecidos**: |
|||
|
|||
* O [Tema Básico](../../Basic-Theme.md) é o tema minimalista com o estilo Bootstrap simples. É **open source e gratuito**. |
|||
* O [Tema LeptonX Lite](../../Themes/LeptonXLite/AspNetCore.md) é um tema moderno e elegante de UI Bootstrap. É ideal se você deseja ter um tema de UI pronto para produção. Também é **open source e gratuito**. |
|||
* O [Tema Lepton](https://commercial.abp.io/themes) é um tema **comercial** desenvolvido pela equipe central do ABP e faz parte da licença [ABP Commercial](https://commercial.abp.io/). |
|||
* O [Tema LeptonX](https://docs.abp.io/en/commercial/latest/themes/lepton-x/index) também é um tema **comercial** desenvolvido pela equipe central do ABP e faz parte da licença [ABP Commercial](https://commercial.abp.io/). Este é o tema padrão após o ABP v6.0.0. |
|||
|
|||
Também existem alguns temas desenvolvidos pela comunidade para o ABP Framework (você pode pesquisar na web). |
|||
|
|||
## Geral |
|||
|
|||
### As Bibliotecas Base |
|||
|
|||
Todos os temas devem depender do pacote NPM [@abp/aspnetcore.mvc.ui.theme.shared](https://www.npmjs.com/package/@abp/aspnetcore.mvc.ui.theme.shared), para que dependam indiretamente das seguintes bibliotecas: |
|||
|
|||
* [Twitter Bootstrap](https://getbootstrap.com/) como o framework HTML/CSS fundamental. |
|||
* [JQuery](https://jquery.com/) para manipulação do DOM. |
|||
* [DataTables.Net](https://datatables.net/) para grades de dados. |
|||
* [JQuery Validation](https://github.com/jquery-validation/jquery-validation) para validação do lado do cliente e [unobtrusive](https://github.com/aspnet/jquery-validation-unobtrusive) validation |
|||
* [FontAwesome](https://fontawesome.com/) como a biblioteca fundamental de fontes CSS. |
|||
* [SweetAlert](https://sweetalert.js.org/) para exibir mensagens de alerta e caixas de diálogo de confirmação. |
|||
* [Toastr](https://github.com/CodeSeven/toastr) para exibir notificações de toast. |
|||
* [Lodash](https://lodash.com/) como uma biblioteca de utilitários. |
|||
* [Luxon](https://moment.github.io/luxon/) para operações de data/hora. |
|||
* [JQuery Form](https://github.com/jquery-form/form) para formulários AJAX. |
|||
* [bootstrap-datepicker](https://github.com/uxsolutions/bootstrap-datepicker) para exibir seletores de data. |
|||
* [Select2](https://select2.org/) para caixas de seleção/combo melhores. |
|||
* [Timeago](http://timeago.yarp.com/) para exibir carimbos de data/hora fuzzy atualizados automaticamente. |
|||
* [malihu-custom-scrollbar-plugin](https://github.com/malihu/malihu-custom-scrollbar-plugin) para barras de rolagem personalizadas. |
|||
|
|||
Essas bibliotecas são selecionadas como as bibliotecas base e estão disponíveis para as aplicações e módulos. |
|||
|
|||
#### Abstrações / Wrappers |
|||
|
|||
Existem algumas abstrações no ABP Framework para tornar seu código independente de algumas dessas bibliotecas também. Exemplos: |
|||
|
|||
* [Tag Helpers](../../Tag-Helpers/Index.md) facilitam a geração de UIs do Bootstrap. |
|||
* As APIs JavaScript [Message](../../JavaScript-API/Message.md) e [Notification](../../JavaScript-API/Notify.md) fornecem abstrações para usar o Sweetalert e o Toastr. |
|||
* O sistema de [Forms & Validation](../../Forms-Validation.md) manipula automaticamente a validação, então você geralmente não digita diretamente nenhum código de validação. |
|||
|
|||
### Os Layouts Padrão |
|||
|
|||
A principal responsabilidade de um tema é fornecer os layouts. Existem **três layouts predefinidos que devem ser implementados por todos os temas**: |
|||
|
|||
* **Application**: O layout padrão usado pelas páginas principais do aplicativo. |
|||
* **Account**: Geralmente usado pelo [módulo de conta](../../Modules/Account.md) para páginas de login, registro, esqueci minha senha... |
|||
* **Empty**: O layout mínimo que não possui componentes de layout. |
|||
|
|||
Os nomes dos layouts são constantes definidas na classe `Volo.Abp.AspNetCore.Mvc.UI.Theming.StandardLayouts`. |
|||
|
|||
#### O Layout de Aplicativo |
|||
|
|||
Este é o layout padrão usado pelas páginas principais do aplicativo. A imagem a seguir mostra a página de gerenciamento de usuários no layout de aplicativo do [Tema Básico](../../Basic-Theme.md): |
|||
|
|||
 |
|||
|
|||
E a mesma página é mostrada abaixo com o layout de aplicativo do [Tema Lepton](https://commercial.abp.io/themes): |
|||
|
|||
 |
|||
|
|||
Como você pode ver, a página é a mesma, mas a aparência é completamente diferente nos temas acima. |
|||
|
|||
O layout de aplicativo normalmente inclui as seguintes partes: |
|||
|
|||
* Um [menu principal](../../Navigation-Menu.md) |
|||
* Uma [barra de ferramentas](../../Toolbars.md) principal com os seguintes componentes: |
|||
* Menu do usuário |
|||
* Dropdown de troca de idioma |
|||
* [Alertas de página](../../Page-Alerts.md) |
|||
* O conteúdo da página (chamado de `RenderBody()`) |
|||
* [Hooks de layout](../../Layout-Hooks.md) |
|||
|
|||
Alguns temas podem fornecer mais partes, como breadcrumbs, cabeçalho e barra de ferramentas da página... etc. Veja a seção *Partes do Layout*. |
|||
|
|||
#### O Layout de Conta |
|||
|
|||
O layout de conta é geralmente usado pelo [módulo de conta](../../Modules/Account.md) para páginas de login, registro, esqueci minha senha... |
|||
|
|||
 |
|||
|
|||
Este layout normalmente fornece as seguintes partes: |
|||
|
|||
* Dropdown de troca de idioma |
|||
* Área de troca de locatário (se a aplicação for [multi-tenant](../../Multi-Tenancy.md) e o locatário atual for resolvido pelo cookie) |
|||
* [Alertas de página](../../Page-Alerts.md) |
|||
* O conteúdo da página (chamado de `RenderBody()`) |
|||
* [Hooks de layout](../../Layout-Hooks.md) |
|||
|
|||
O [Tema Básico](../../Basic-Theme.md) também renderiza a barra de navegação superior para este layout (como mostrado acima). |
|||
|
|||
Aqui está o layout de conta do Tema Lepton: |
|||
|
|||
 |
|||
|
|||
O [Tema Lepton](https://commercial.abp.io/themes) mostra o logotipo do aplicativo e o rodapé neste layout. |
|||
|
|||
> Você pode substituir completamente ou parcialmente os layouts do tema em um aplicativo para [personalizá-lo](../../Customization-User-Interface.md). |
|||
|
|||
#### O Layout Vazio |
|||
|
|||
O layout vazio fornece uma página vazia. Normalmente inclui as seguintes partes: |
|||
|
|||
* [Alertas de página](../../Page-Alerts.md) |
|||
* O conteúdo da página (chamado de `RenderBody()`) |
|||
* [Hooks de layout](../../Layout-Hooks.md) |
|||
|
|||
## Implementando um Tema |
|||
|
|||
### A Forma Mais Fácil |
|||
|
|||
A forma mais fácil de criar um novo tema é adicionar o módulo [Código-fonte do Tema Básico](https://github.com/abpframework/abp/tree/dev/modules/basic-theme) com os códigos-fonte e personalizá-lo. |
|||
|
|||
```bash |
|||
abp add-package Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic --with-source-code --add-to-solution-file |
|||
``` |
|||
|
|||
### A Interface ITheme |
|||
|
|||
A interface `ITheme` é usada pelo ABP Framework para selecionar o layout para a página atual. Um tema deve implementar esta interface para fornecer o caminho do layout solicitado. |
|||
|
|||
Esta é a implementação da `ITheme` do [Tema Básico](../../Basic-Theme.md). |
|||
|
|||
````csharp |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Theming; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic |
|||
{ |
|||
[ThemeName(Name)] |
|||
public class BasicTheme : ITheme, ITransientDependency |
|||
{ |
|||
public const string Name = "Basic"; |
|||
|
|||
public virtual string GetLayout(string name, bool fallbackToDefault = true) |
|||
{ |
|||
switch (name) |
|||
{ |
|||
case StandardLayouts.Application: |
|||
return "~/Themes/Basic/Layouts/Application.cshtml"; |
|||
case StandardLayouts.Account: |
|||
return "~/Themes/Basic/Layouts/Account.cshtml"; |
|||
case StandardLayouts.Empty: |
|||
return "~/Themes/Basic/Layouts/Empty.cshtml"; |
|||
default: |
|||
return fallbackToDefault |
|||
? "~/Themes/Basic/Layouts/Application.cshtml" |
|||
: null; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
* O atributo `[ThemeName]` é obrigatório e um tema deve ter um nome único, `Basic` neste exemplo. |
|||
* O método `GetLayout` deve retornar um caminho se o layout solicitado (`name`) for fornecido pelo tema. *Os Layouts Padrão* devem ser implementados se o tema for destinado a ser usado por um aplicativo padrão. Ele pode implementar layouts adicionais. |
|||
|
|||
Depois que o tema implementa a interface `ITheme`, ele deve adicionar o tema às `AbpThemingOptions` no método `ConfigureServices` do [módulo](../../Module-Development-Basics.md). |
|||
|
|||
````csharp |
|||
Configure<AbpThemingOptions>(options => |
|||
{ |
|||
options.Themes.Add<BasicTheme>(); |
|||
}); |
|||
```` |
|||
|
|||
#### O Serviço IThemeSelector |
|||
|
|||
O ABP Framework permite usar vários temas juntos. É por isso que `options.Themes` é uma lista. O serviço `IThemeSelector` seleciona o tema em tempo de execução. O desenvolvedor da aplicação pode definir `AbpThemingOptions.DefaultThemeName` para definir o tema a ser usado ou substituir a implementação do serviço `IThemeSelector` (a implementação padrão é `DefaultThemeSelector`) para controlar completamente a seleção do tema em tempo de execução. |
|||
|
|||
### Bundles |
|||
|
|||
O [sistema de agrupamento](../../Bundling-Minification.md) fornece uma maneira padrão de importar arquivos de estilo e script nas páginas. Existem dois pacotes padrão definidos pelo ABP Framework: |
|||
|
|||
* `StandardBundles.Styles.Global`: O pacote global que inclui os arquivos de estilo usados em todas as páginas. Normalmente, inclui os arquivos CSS das Bibliotecas Base. |
|||
* `StandardBundles.Scripts.Global`: O pacote global que inclui os arquivos de script usados em todas as páginas. Normalmente, inclui os arquivos JavaScript das Bibliotecas Base. |
|||
|
|||
Um tema geralmente estende esses pacotes padrão adicionando arquivos CSS/JavaScript específicos do tema. |
|||
|
|||
A melhor maneira de definir novos pacotes é herdar dos pacotes padrão e adicioná-los às `AbpBundlingOptions`, como mostrado abaixo (este código é do [Tema Básico](../../Basic-Theme.md)): |
|||
|
|||
````csharp |
|||
Configure<AbpBundlingOptions>(options => |
|||
{ |
|||
options |
|||
.StyleBundles |
|||
.Add(BasicThemeBundles.Styles.Global, bundle => |
|||
{ |
|||
bundle |
|||
.AddBaseBundles(StandardBundles.Styles.Global) |
|||
.AddContributors(typeof(BasicThemeGlobalStyleContributor)); |
|||
}); |
|||
|
|||
options |
|||
.ScriptBundles |
|||
.Add(BasicThemeBundles.Scripts.Global, bundle => |
|||
{ |
|||
bundle |
|||
.AddBaseBundles(StandardBundles.Scripts.Global) |
|||
.AddContributors(typeof(BasicThemeGlobalScriptContributor)); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
`BasicThemeGlobalStyleContributor` e `BasicThemeGlobalScriptContributor` são contribuidores de pacotes. Por exemplo, `BasicThemeGlobalStyleContributor` é definido como mostrado abaixo: |
|||
|
|||
```csharp |
|||
public class BasicThemeGlobalStyleContributor : BundleContributor |
|||
{ |
|||
public override void ConfigureBundle(BundleConfigurationContext context) |
|||
{ |
|||
context.Files.Add("/themes/basic/layout.css"); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
Em seguida, o tema pode renderizar esses pacotes em um layout. Por exemplo, você pode renderizar os Estilos Globais como mostrado abaixo: |
|||
|
|||
````html |
|||
<abp-style-bundle name="@BasicThemeBundles.Styles.Global" /> |
|||
```` |
|||
|
|||
Consulte o documento [Bundle & Minification](../../Bundling-Minification.md) para entender melhor o sistema de agrupamento. |
|||
|
|||
### Partes do Layout |
|||
|
|||
Um layout típico consiste em várias partes. O tema deve incluir as partes necessárias em cada layout. |
|||
|
|||
**Exemplo: O Tema Básico tem as seguintes partes para o Layout de Aplicativo** |
|||
|
|||
 |
|||
|
|||
O código do aplicativo e dos módulos só pode mostrar conteúdo na parte de Conteúdo da Página. Se eles precisarem alterar as outras partes (adicionar um item de menu, adicionar um item de barra de ferramentas, alterar o nome do aplicativo na área de marcação...), eles devem usar as APIs do ABP Framework. |
|||
|
|||
As seções a seguir explicam as partes fundamentais pré-definidas pelo ABP Framework e que podem ser implementadas pelos temas. |
|||
|
|||
> É uma boa prática dividir o layout em componentes/partials, para que o aplicativo final possa substituí-los parcialmente para fins de personalização. |
|||
|
|||
#### Marcação |
|||
|
|||
O serviço `IBrandingProvider` deve ser usado para obter o nome e a URL do logotipo do aplicativo para renderizar na parte de Marcação. |
|||
|
|||
O [Modelo de Inicialização do Aplicativo](../../Startup-Templates/Application.md) tem uma implementação dessa interface para definir os valores pelo desenvolvedor da aplicação. |
|||
|
|||
#### Menu Principal |
|||
|
|||
O serviço `IMenuManager` é usado para obter os itens do menu principal e renderizá-los no layout. |
|||
|
|||
**Exemplo: Obter o Menu Principal para renderizar em um componente de visualização** |
|||
|
|||
```csharp |
|||
public class MainNavbarMenuViewComponent : AbpViewComponent |
|||
{ |
|||
private readonly IMenuManager _menuManager; |
|||
|
|||
public MainNavbarMenuViewComponent(IMenuManager menuManager) |
|||
{ |
|||
_menuManager = menuManager; |
|||
} |
|||
|
|||
public async Task<IViewComponentResult> InvokeAsync() |
|||
{ |
|||
var menu = await _menuManager.GetAsync(StandardMenus.Main); |
|||
return View("~/Themes/Basic/Components/Menu/Default.cshtml", menu); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
Consulte o documento [Navegação / Menus](../../Navigation-Menu.md) para saber mais sobre o sistema de navegação. |
|||
|
|||
#### Barra de Ferramentas Principal |
|||
|
|||
O serviço `IToolbarManager` é usado para obter os itens da Barra de Ferramentas Principal e renderizá-los no layout. Cada item desta barra de ferramentas é um componente de visualização, então ele pode incluir qualquer tipo de elemento de UI. Injete o `IToolbarManager` e use o `GetAsync` para obter os itens da barra de ferramentas: |
|||
|
|||
````csharp |
|||
var toolbar = await _toolbarManager.GetAsync(StandardToolbars.Main); |
|||
```` |
|||
|
|||
> Consulte o documento [Barras de Ferramentas](../../Toolbars.md) para saber mais sobre o sistema de barras de ferramentas. |
|||
|
|||
O tema tem a responsabilidade de adicionar dois itens pré-definidos à barra de ferramentas principal: Seleção de Idioma e Menu do Usuário. Para fazer isso, crie uma classe que implemente a interface `IToolbarContributor` e adicione-a às `AbpToolbarOptions`, como mostrado abaixo: |
|||
|
|||
```csharp |
|||
Configure<AbpToolbarOptions>(options => |
|||
{ |
|||
options.Contributors.Add(new BasicThemeMainTopToolbarContributor()); |
|||
}); |
|||
``` |
|||
|
|||
##### Seleção de Idioma |
|||
|
|||
O item de barra de ferramentas Seleção de Idioma é geralmente um dropdown que é usado para alternar entre idiomas. O `ILanguageProvider` é usado para obter a lista de idiomas disponíveis e `CultureInfo.CurrentUICulture` é usado para saber o idioma atual. |
|||
|
|||
O endpoint `/Abp/Languages/Switch` pode ser usado para alternar o idioma. Este endpoint aceita os seguintes parâmetros de string de consulta: |
|||
|
|||
* `culture`: O idioma selecionado, como `en-US` ou `en`. |
|||
* `uiCulture`: O idioma de IU selecionado, como `en-US` ou `en`. |
|||
* `returnUrl` (opcional): Pode ser usado para retornar uma determinada URL após a troca de idioma. |
|||
|
|||
`culture` e `uiCulture` devem corresponder a um dos idiomas disponíveis. O ABP Framework define um cookie de cultura no endpoint `/Abp/Languages/Switch`. |
|||
|
|||
##### Menu do Usuário |
|||
|
|||
O menu do usuário inclui links relacionados à conta do usuário. O `IMenuManager` é usado da mesma forma que o Menu Principal, mas desta vez com o parâmetro `StandardMenus.User`, como mostrado abaixo: |
|||
|
|||
````csharp |
|||
var menu = await _menuManager.GetAsync(StandardMenus.User); |
|||
```` |
|||
|
|||
Os serviços [ICurrentUser](../../CurrentUser.md) e [ICurrentTenant](../../Multi-Tenancy.md) podem ser usados para obter os nomes do usuário e do locatário atual. |
|||
|
|||
#### Alertas de Página |
|||
|
|||
O serviço `IAlertManager` é usado para obter os alertas de página atuais para renderizar no layout. Use a lista `Alerts` do `IAlertManager`. Geralmente é renderizado logo antes do conteúdo da página (`RenderBody()`). |
|||
|
|||
Consulte o documento [Alertas de Página](../../Page-Alerts.md) para saber mais. |
|||
|
|||
#### Hooks de Layout |
|||
|
|||
Como o Layout está no pacote do tema, o aplicativo final ou qualquer módulo não pode manipular diretamente o conteúdo do layout. O sistema de [Hooks de Layout](../../Layout-Hooks.md) permite injetar componentes em pontos específicos do layout. |
|||
|
|||
O tema é responsável por renderizar os hooks no local correto. |
|||
|
|||
**Exemplo: Renderizar o Hook `LayoutHooks.Head.First` no Layout de Aplicativo** |
|||
|
|||
````html |
|||
<head> |
|||
@await Component.InvokeLayoutHookAsync(LayoutHooks.Head.First, StandardLayouts.Application) |
|||
... |
|||
```` |
|||
|
|||
Consulte o documento [Hooks de Layout](../../Layout-Hooks.md) para saber mais sobre os hooks de layout padrão. |
|||
|
|||
#### Seções de Script / Estilo |
|||
|
|||
Todo layout deve renderizar as seguintes seções opcionais: |
|||
|
|||
* A seção `styles` é renderizada no final do `head`, logo antes do `LayoutHooks.Head.Last`. |
|||
* A seção `scripts` é renderizada no final do `body`, logo antes do `LayoutHooks.Body.Last`. |
|||
|
|||
Dessa forma, a página pode importar estilos e scripts para o layout. |
|||
|
|||
**Exemplo: Renderizar a seção `styles`** |
|||
|
|||
````csharp |
|||
@await RenderSectionAsync("styles", required: false) |
|||
```` |
|||
|
|||
#### Seção de Barra de Ferramentas de Conteúdo |
|||
|
|||
Outra seção pré-definida é a seção de Barra de Ferramentas de Conteúdo, que pode ser usada pelas páginas para adicionar código logo antes do conteúdo da página. O Tema Básico a renderiza da seguinte forma: |
|||
|
|||
````html |
|||
<div id="AbpContentToolbar"> |
|||
<div class="text-end mb-2"> |
|||
@RenderSection("content_toolbar", false) |
|||
</div> |
|||
</div> |
|||
```` |
|||
|
|||
O id da div de contêiner deve ser `AbpContentToolbar`. Esta seção deve vir antes do `RenderBody()`. |
|||
|
|||
#### Recursos de Widgets |
|||
|
|||
O [Sistema de Widgets](../../Widgets.md) permite definir widgets reutilizáveis com seus próprios arquivos de estilo/script. Todos os layouts devem renderizar o estilo e os scripts do widget. |
|||
|
|||
**Estilos de Widget** são renderizados da seguinte forma, logo antes da seção `styles`, após o pacote de estilo global: |
|||
|
|||
````csharp |
|||
@await Component.InvokeAsync(typeof(WidgetStylesViewComponent)) |
|||
```` |
|||
|
|||
**Scripts de Widget** são renderizados da seguinte forma, logo antes da seção `scripts`, após o pacote de script global: |
|||
|
|||
````csharp |
|||
@await Component.InvokeAsync(typeof(WidgetScriptsViewComponent)) |
|||
```` |
|||
|
|||
#### Scripts ABP |
|||
|
|||
O ABP tem alguns scripts especiais que devem ser incluídos em todos os layouts. Eles não estão incluídos nos pacotes globais, pois são criados dinamicamente com base no usuário atual. |
|||
|
|||
Os scripts do ABP (`ApplicationConfigurationScript` e `ServiceProxyScript`) devem ser adicionados logo após o pacote de script global, como mostrado abaixo: |
|||
|
|||
````html |
|||
<script src="~/Abp/ApplicationConfigurationScript"></script> |
|||
<script src="~/Abp/ServiceProxyScript"></script> |
|||
```` |
|||
|
|||
#### Título da Página, Item de Menu Selecionado e Breadcrumbs |
|||
|
|||
O serviço `IPageLayout` pode ser injetado por qualquer página para definir o título da página, o nome do item de menu selecionado e os itens de breadcrumbs. Em seguida, o tema pode usar este serviço para obter esses valores e renderizá-los na UI. |
|||
|
|||
O Tema Básico não implementa este serviço, mas o Tema Lepton implementa: |
|||
|
|||
 |
|||
|
|||
Consulte o documento [Cabeçalho da Página](../../Page-Header.md) para saber mais. |
|||
|
|||
#### Troca de Locatário |
|||
|
|||
O Layout de Conta deve permitir ao usuário trocar o locatário atual se a aplicação for multi-tenant e o locatário for resolvido a partir dos cookies. Consulte o [Layout de Conta do Tema Básico](https://github.com/abpframework/abp/blob/dev/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml) como um exemplo de implementação. |
|||
|
|||
### Classes de Layout |
|||
|
|||
Os Layouts Padrão (`Application`, `Account` e `Empty`) devem adicionar as seguintes classes CSS à tag `body`: |
|||
|
|||
* `abp-application-layout` para o layout `Application`. |
|||
* `abp-account-layout` para o layout `Account`. |
|||
* `abp-empty-layout` para o layout `Empty`. |
|||
|
|||
Dessa forma, os aplicativos ou módulos podem ter seletores com base no layout atual. |
|||
|
|||
### RTL |
|||
|
|||
Para oferecer suporte a idiomas da direita para a esquerda, o Layout deve verificar a cultura atual e adicionar `dir="rtl"` à tag `html` e a classe CSS `rtl` à tag `body`. |
|||
|
|||
Você pode verificar `CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft` para entender se o idioma atual é um idioma RTL. |
|||
|
|||
### O Pacote NPM |
|||
|
|||
Um tema deve ter um pacote NPM que dependa do pacote [@abp/aspnetcore.mvc.ui.theme.shared](https://www.npmjs.com/package/@abp/aspnetcore.mvc.ui.theme.shared). Dessa forma, ele herda todas as Bibliotecas Base. Se o tema exigir bibliotecas adicionais, ele deve definir essas dependências também. |
|||
|
|||
As aplicações usam o sistema de [Gerenciamento de Pacotes do Lado do Cliente](../../Client-Side-Package-Management.md) para adicionar bibliotecas do lado do cliente ao projeto. Portanto, se uma aplicação usar seu tema, ela deve adicionar a dependência do pacote NPM do seu tema, bem como a dependência do pacote NuGet. |
|||
|
|||
@ -0,0 +1,95 @@ |
|||
# ASP.NET Core MVC / Razor Pages UI: Barras de Ferramentas |
|||
|
|||
O sistema de barras de ferramentas é usado para definir **barras de ferramentas** na interface do usuário. Módulos (ou sua aplicação) podem adicionar **itens** a uma barra de ferramentas e, em seguida, o [tema](Theming.md) renderiza a barra de ferramentas no **layout**. |
|||
|
|||
Existe apenas uma **barra de ferramentas padrão** chamada "Principal" (definida como uma constante: `StandardToolbars.Main`). O [Tema Básico](Basic-Theme) renderiza a barra de ferramentas principal como mostrado abaixo: |
|||
|
|||
 |
|||
|
|||
Na captura de tela acima, existem dois itens adicionados à barra de ferramentas principal: o componente de alternância de idioma e o menu do usuário. Você pode adicionar seus próprios itens aqui. |
|||
|
|||
Além disso, o [Tema LeptonX Lite](../../Themes/LeptonXLite/AspNetCore.md) possui duas barras de ferramentas diferentes para visualizações de desktop e móveis, definidas como constantes: `LeptonXLiteToolbars.Main`, `LeptonXLiteToolbars.MainMobile`. |
|||
|
|||
| LeptonXLiteToolbars.Main | LeptonXLiteToolbars.MainMobile | |
|||
| :---: | :---: | |
|||
|  |  | |
|||
|
|||
## Exemplo: Adicionar um Ícone de Notificação |
|||
|
|||
Neste exemplo, vamos adicionar um **ícone de notificação (sino)** à esquerda do item de alternância de idioma. Um item na barra de ferramentas deve ser um **componente de visualização**. Então, primeiro, crie um novo componente de visualização em seu projeto: |
|||
|
|||
 |
|||
|
|||
**NotificationViewComponent.cs** |
|||
|
|||
````csharp |
|||
public class NotificationViewComponent : AbpViewComponent |
|||
{ |
|||
public async Task<IViewComponentResult> InvokeAsync() |
|||
{ |
|||
return View("/Pages/Shared/Components/Notification/Default.cshtml"); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
**Default.cshtml** |
|||
|
|||
````xml |
|||
<div id="MainNotificationIcon" style="color: white; margin: 8px;"> |
|||
<i class="far fa-bell"></i> |
|||
</div> |
|||
```` |
|||
|
|||
Agora, podemos criar uma classe que implementa a interface `IToolbarContributor`: |
|||
|
|||
````csharp |
|||
public class MyToolbarContributor : IToolbarContributor |
|||
{ |
|||
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context) |
|||
{ |
|||
if (context.Toolbar.Name == StandardToolbars.Main) |
|||
{ |
|||
context.Toolbar.Items |
|||
.Insert(0, new ToolbarItem(typeof(NotificationViewComponent))); |
|||
} |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Você pode usar a [autorização](../../Authorization.md) para decidir se deve adicionar um `ToolbarItem`. |
|||
|
|||
````csharp |
|||
if (await context.IsGrantedAsync("NomeDaMinhaPermissao")) |
|||
{ |
|||
//...adicionar itens da barra de ferramentas |
|||
} |
|||
```` |
|||
|
|||
Você pode usar o método de extensão `RequirePermissions` como um atalho. Também é mais eficiente, o ABP otimiza a verificação de permissão para todos os itens. |
|||
|
|||
````csharp |
|||
context.Toolbar.Items.Insert(0, new ToolbarItem(typeof(NotificationViewComponent)).RequirePermissions("NomeDaMinhaPermissao")); |
|||
```` |
|||
|
|||
Essa classe adiciona o `NotificationViewComponent` como o primeiro item na barra de ferramentas `Main`. |
|||
|
|||
Por fim, você precisa adicionar esse contribuidor às `AbpToolbarOptions`, no `ConfigureServices` do seu [módulo](../../Module-Development-Basics.md): |
|||
|
|||
````csharp |
|||
Configure<AbpToolbarOptions>(options => |
|||
{ |
|||
options.Contributors.Add(new MyToolbarContributor()); |
|||
}); |
|||
```` |
|||
|
|||
Isso é tudo, você verá o ícone de notificação na barra de ferramentas quando executar a aplicação: |
|||
|
|||
 |
|||
|
|||
`NotificationViewComponent` neste exemplo simplesmente retorna uma visualização sem nenhum dado. Na vida real, provavelmente você desejará **consultar o banco de dados** (ou chamar uma API HTTP) para obter notificações e passá-las para a visualização. Se necessário, você pode adicionar um arquivo `JavaScript` ou `CSS` ao [pacote](Bundling-Minification.md) global para o item da barra de ferramentas. |
|||
|
|||
## IToolbarManager |
|||
|
|||
`IToolbarManager` é usado para renderizar a barra de ferramentas. Ele retorna os itens da barra de ferramentas por um nome de barra de ferramentas. Isso é geralmente usado pelos [temas](Theming.md) para renderizar a barra de ferramentas no layout. |
|||
@ -0,0 +1,526 @@ |
|||
# Widgets |
|||
|
|||
ABP fornece um modelo e infraestrutura para criar **widgets reutilizáveis**. O sistema de widgets é uma extensão dos [Componentes de Visualização do ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components). Os widgets são especialmente úteis quando você deseja: |
|||
|
|||
* Ter dependências de **scripts e estilos** para o seu widget. |
|||
* Criar **painéis de controle** com widgets usados dentro. |
|||
* Definir widgets em **[módulos](../../Module-Development-Basics.md)** reutilizáveis. |
|||
* Cooperar com widgets com sistemas de **[autorização](../../Authorization.md)** e **[agrupamento](Bundling-Minification.md)**. |
|||
|
|||
## Definição Básica de Widget |
|||
|
|||
### Criar um Componente de Visualização |
|||
|
|||
Como primeiro passo, crie um novo Componente de Visualização regular do ASP.NET Core: |
|||
|
|||
 |
|||
|
|||
**MySimpleWidgetViewComponent.cs**: |
|||
|
|||
````csharp |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace DashboardDemo.Web.Pages.Components.MySimpleWidget |
|||
{ |
|||
public class MySimpleWidgetViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View(); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Herdar de `AbpViewComponent` não é obrigatório. Você pode herdar do `ViewComponent` padrão do ASP.NET Core. `AbpViewComponent` apenas define algumas propriedades úteis básicas. |
|||
|
|||
Você pode injetar um serviço e usá-lo no método `Invoke` para obter alguns dados do serviço. Talvez seja necessário tornar o método Invoke assíncrono, como `public async Task<IViewComponentResult> InvokeAsync()`. Consulte o documento [Componentes de Visualização do ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components) para ver todos os diferentes usos. |
|||
|
|||
**Default.cshtml**: |
|||
|
|||
```xml |
|||
<div class="my-simple-widget"> |
|||
<h2>My Simple Widget</h2> |
|||
<p>This is a simple widget!</p> |
|||
</div> |
|||
``` |
|||
|
|||
### Definir o Widget |
|||
|
|||
Adicione um atributo `Widget` à classe `MySimpleWidgetViewComponent` para marcar este componente de visualização como um widget: |
|||
|
|||
````csharp |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
|||
|
|||
namespace DashboardDemo.Web.Pages.Components.MySimpleWidget |
|||
{ |
|||
[Widget] |
|||
public class MySimpleWidgetViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View(); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
## Renderizando um Widget |
|||
|
|||
Renderizar um widget é bastante padrão. Use o método `Component.InvokeAsync` em uma view/página razor como você faria para qualquer componente de visualização. Exemplos: |
|||
|
|||
````xml |
|||
@await Component.InvokeAsync("MySimpleWidget") |
|||
@await Component.InvokeAsync(typeof(MySimpleWidgetViewComponent)) |
|||
```` |
|||
|
|||
A primeira abordagem usa o nome do widget, enquanto a segunda abordagem usa o tipo do componente de visualização. |
|||
|
|||
### Widgets com Argumentos |
|||
|
|||
O sistema de componentes de visualização do ASP.NET Core permite que você aceite argumentos para componentes de visualização. O exemplo de componente de visualização abaixo aceita `startDate` e `endDate` e usa esses argumentos para recuperar dados de um serviço. |
|||
|
|||
````csharp |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
|||
|
|||
namespace DashboardDemo.Web.Pages.Shared.Components.CountersWidget |
|||
{ |
|||
[Widget] |
|||
public class CountersWidgetViewComponent : AbpViewComponent |
|||
{ |
|||
private readonly IDashboardAppService _dashboardAppService; |
|||
|
|||
public CountersWidgetViewComponent(IDashboardAppService dashboardAppService) |
|||
{ |
|||
_dashboardAppService = dashboardAppService; |
|||
} |
|||
|
|||
public async Task<IViewComponentResult> InvokeAsync( |
|||
DateTime startDate, DateTime endDate) |
|||
{ |
|||
var result = await _dashboardAppService.GetCountersWidgetAsync( |
|||
new CountersWidgetInputDto |
|||
{ |
|||
StartDate = startDate, |
|||
EndDate = endDate |
|||
} |
|||
); |
|||
|
|||
return View(result); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Agora, você precisa passar um objeto anônimo para passar argumentos, como mostrado abaixo: |
|||
|
|||
````xml |
|||
@await Component.InvokeAsync("CountersWidget", new |
|||
{ |
|||
startDate = DateTime.Now.Subtract(TimeSpan.FromDays(7)), |
|||
endDate = DateTime.Now |
|||
}) |
|||
```` |
|||
|
|||
## Nome do Widget |
|||
|
|||
O nome padrão dos componentes de visualização é calculado com base no nome do tipo do componente de visualização. Se o tipo do componente de visualização for `MySimpleWidgetViewComponent`, então o nome do widget será `MySimpleWidget` (remove o sufixo `ViewComponent`). É assim que o ASP.NET Core calcula o nome de um componente de visualização. |
|||
|
|||
Para personalizar o nome do widget, basta usar o atributo `ViewComponent` padrão do ASP.NET Core: |
|||
|
|||
```csharp |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
|||
|
|||
namespace DashboardDemo.Web.Pages.Components.MySimpleWidget |
|||
{ |
|||
[Widget] |
|||
[ViewComponent(Name = "MyCustomNamedWidget")] |
|||
public class MySimpleWidgetViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View("~/Pages/Components/MySimpleWidget/Default.cshtml"); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
O ABP respeitará o nome personalizado ao lidar com o widget. |
|||
|
|||
> Se o nome do componente de visualização e o nome da pasta do componente de visualização não corresponderem, talvez seja necessário escrever manualmente o caminho da visualização, como feito neste exemplo. |
|||
|
|||
### Nome de Exibição |
|||
|
|||
Você também pode definir um nome de exibição legível por humanos e localizável para o widget. Esse nome de exibição pode ser usado na interface do usuário quando necessário. O nome de exibição é opcional e pode ser definido usando as propriedades do atributo `Widget`: |
|||
|
|||
````csharp |
|||
using DashboardDemo.Localization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
|||
|
|||
namespace DashboardDemo.Web.Pages.Components.MySimpleWidget |
|||
{ |
|||
[Widget( |
|||
DisplayName = "MySimpleWidgetDisplayName", //Chave de localização |
|||
DisplayNameResource = typeof(DashboardDemoResource) //recurso de localização |
|||
)] |
|||
public class MySimpleWidgetViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View(); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
Consulte [o documento de localização](../../Localization.md) para saber mais sobre recursos e chaves de localização. |
|||
|
|||
## Dependências de Estilo e Script |
|||
|
|||
Existem alguns desafios quando seu widget possui arquivos de script e estilo; |
|||
|
|||
* Qualquer página que usa o widget também deve incluir os arquivos de **script e estilos** dele na página. |
|||
* A página também deve se preocupar com as **bibliotecas/arquivos dependentes** do widget. |
|||
|
|||
O ABP resolve esses problemas quando você relaciona corretamente os recursos com o widget. Você não precisa se preocupar com as dependências do widget ao usá-lo. |
|||
|
|||
### Definindo como Caminhos Simples de Arquivo |
|||
|
|||
O widget de exemplo abaixo adiciona um arquivo de estilo e um arquivo de script: |
|||
|
|||
````csharp |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
|||
|
|||
namespace DashboardDemo.Web.Pages.Components.MySimpleWidget |
|||
{ |
|||
[Widget( |
|||
StyleFiles = new[] { "/Pages/Components/MySimpleWidget/Default.css" }, |
|||
ScriptFiles = new[] { "/Pages/Components/MySimpleWidget/Default.js" } |
|||
)] |
|||
public class MySimpleWidgetViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View(); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
O ABP leva em consideração essas dependências e as adiciona corretamente à visualização/página quando você usa o widget. Os arquivos de estilo/script podem ser **físicos ou virtuais**. Está completamente integrado ao [Sistema de Arquivos Virtual](../../Virtual-File-System.md). |
|||
|
|||
### Definindo Contribuidores de Pacote |
|||
|
|||
Todos os recursos para os widgets usados em uma página são adicionados como um **pacote** (agrupados e minificados em produção se você não configurar de outra forma). Além de adicionar um arquivo simples, você pode aproveitar ao máximo os contribuidores de pacote. |
|||
|
|||
O código de exemplo abaixo faz o mesmo que o código acima, mas define e usa contribuidores de pacote: |
|||
|
|||
````csharp |
|||
using System.Collections.Generic; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
|||
|
|||
namespace DashboardDemo.Web.Pages.Components.MySimpleWidget |
|||
{ |
|||
[Widget( |
|||
StyleTypes = new []{ typeof(MySimpleWidgetStyleBundleContributor) }, |
|||
ScriptTypes = new[]{ typeof(MySimpleWidgetScriptBundleContributor) } |
|||
)] |
|||
public class MySimpleWidgetViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View(); |
|||
} |
|||
} |
|||
|
|||
public class MySimpleWidgetStyleBundleContributor : BundleContributor |
|||
{ |
|||
public override void ConfigureBundle(BundleConfigurationContext context) |
|||
{ |
|||
context.Files |
|||
.AddIfNotContains("/Pages/Components/MySimpleWidget/Default.css"); |
|||
} |
|||
} |
|||
|
|||
public class MySimpleWidgetScriptBundleContributor : BundleContributor |
|||
{ |
|||
public override void ConfigureBundle(BundleConfigurationContext context) |
|||
{ |
|||
context.Files |
|||
.AddIfNotContains("/Pages/Components/MySimpleWidget/Default.js"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
```` |
|||
|
|||
O sistema de contribuição de pacotes é muito poderoso. Se o seu widget usa uma biblioteca JavaScript para renderizar um gráfico, você pode declará-la como uma dependência, para que a biblioteca JavaScript seja automaticamente adicionada à página se ainda não tiver sido adicionada. Dessa forma, a página que usa seu widget não se preocupa com as dependências. |
|||
|
|||
Consulte a documentação de [agrupamento e minificação](Bundling-Minification.md) para obter mais informações sobre esse sistema. |
|||
|
|||
## RefreshUrl |
|||
|
|||
Um widget pode projetar uma `RefreshUrl` que é usada sempre que o widget precisa ser atualizado. Se for definido, o widget é renderizado novamente no lado do servidor em cada atualização (consulte o método de atualização do `WidgetManager` abaixo). |
|||
|
|||
````csharp |
|||
[Widget(RefreshUrl = "Widgets/Counters")] |
|||
public class CountersWidgetViewComponent : AbpViewComponent |
|||
{ |
|||
|
|||
} |
|||
```` |
|||
|
|||
Depois de definir uma `RefreshUrl` para o seu widget, você precisa fornecer um endpoint para renderizá-lo e retorná-lo: |
|||
|
|||
````csharp |
|||
[Route("Widgets")] |
|||
public class CountersWidgetController : AbpController |
|||
{ |
|||
[HttpGet] |
|||
[Route("Counters")] |
|||
public IActionResult Counters(DateTime startDate, DateTime endDate) |
|||
{ |
|||
return ViewComponent("CountersWidget", new {startDate, endDate}); |
|||
} |
|||
} |
|||
```` |
|||
|
|||
A rota `Widgets/Counters` corresponde à `RefreshUrl` declarada anteriormente. |
|||
|
|||
> Um widget deve ser atualizado de duas maneiras: Na primeira maneira, quando você usa uma `RefreshUrl`, ele é renderizado novamente no servidor e substituído pelo HTML retornado pelo servidor. Na segunda maneira, o widget obtém dados (geralmente um objeto JSON) do servidor e atualiza-se no lado do cliente (consulte o método de atualização na seção Widget JavaScript API). |
|||
|
|||
## AutoInitialize |
|||
|
|||
O atributo `Widget` tem uma propriedade `AutoInitialize` (`bool`) que pode ser definida como `true` para inicializar automaticamente um widget quando a página estiver pronta e sempre que o widget for adicionado ao DOM. O valor padrão é `false`. |
|||
|
|||
Se um widget estiver configurado para ser inicializado automaticamente, então um `WidgetManager` (consulte abaixo) é criado e inicializado automaticamente para instâncias deste widget. Isso é útil quando as instâncias do widget não estão agrupadas e funcionam separadamente (não é necessário inicializar ou atualizar juntas). |
|||
|
|||
Definir o `AutoInitialize` como `true` é equivalente a escrever esse código você mesmo: |
|||
|
|||
````js |
|||
$('.abp-widget-wrapper[data-widget-name="MySimpleWidget"]') |
|||
.each(function () { |
|||
var widgetManager = new abp.WidgetManager({ |
|||
wrapper: $(this), |
|||
}); |
|||
|
|||
widgetManager.init($(this)); |
|||
}); |
|||
```` |
|||
|
|||
> `AutoInitialize` também suporta widgets carregados/atualizados via AJAX (adicionados ao DOM posteriormente) e/ou usados de forma aninhada (um widget dentro de outro widget). Se você não precisa agrupar vários widgets e controlar com um único `WidgetManager`, `AutoInitialize` é a abordagem recomendada. |
|||
|
|||
## API JavaScript do Widget |
|||
|
|||
Um widget pode precisar ser renderizado e atualizado no lado do cliente. Nesses casos, você pode usar o `WidgetManager` do ABP e definir APIs para seus widgets. |
|||
|
|||
### WidgetManager |
|||
|
|||
O `WidgetManager` é usado para inicializar e atualizar um ou mais widgets. Crie um novo `WidgetManager` da seguinte forma: |
|||
|
|||
````js |
|||
$(function() { |
|||
var myWidgetManager = new abp.WidgetManager('#MyDashboardWidgetsArea'); |
|||
}) |
|||
```` |
|||
|
|||
`MyDashboardWidgetsArea` pode conter um ou mais widgets dentro. |
|||
|
|||
> Usar o `WidgetManager` dentro do document.ready (como acima) é uma boa prática, pois suas funções usam o DOM e precisam que o DOM esteja pronto. |
|||
|
|||
#### WidgetManager.init() |
|||
|
|||
`init` simplesmente inicializa o `WidgetManager` e chama os métodos `init` dos widgets relacionados, se eles estiverem definidos (consulte a seção Widget JavaScript API abaixo) |
|||
|
|||
```js |
|||
myWidgetManager.init(); |
|||
``` |
|||
|
|||
#### WidgetManager.refresh() |
|||
|
|||
O método `refresh` atualiza todos os widgets relacionados a este `WidgetManager`: |
|||
|
|||
```` |
|||
myWidgetManager.refresh(); |
|||
```` |
|||
|
|||
#### Opções do WidgetManager |
|||
|
|||
O `WidgetManager` tem algumas opções adicionais. |
|||
|
|||
##### Filtro do Formulário |
|||
|
|||
Se seus widgets exigirem parâmetros/filtros, você geralmente terá um formulário para filtrar os widgets. Nesses casos, você pode criar um formulário que tenha alguns elementos de formulário e uma área de painel de controle com alguns widgets dentro. Exemplo: |
|||
|
|||
````xml |
|||
<form method="get" id="MyDashboardFilterForm"> |
|||
...elementos do formulário |
|||
</form> |
|||
|
|||
<div id="MyDashboardWidgetsArea" data-widget-filter="#MyDashboardFilterForm"> |
|||
...widgets |
|||
</div> |
|||
```` |
|||
|
|||
O atributo `data-widget-filter` relaciona o formulário com os widgets. Sempre que o formulário for enviado, todos os widgets serão atualizados automaticamente com os campos do formulário como filtro. |
|||
|
|||
Em vez do atributo `data-widget-filter`, você pode usar o parâmetro `filterForm` do construtor do `WidgetManager`. Exemplo: |
|||
|
|||
````js |
|||
var myWidgetManager = new abp.WidgetManager({ |
|||
wrapper: '#MyDashboardWidgetsArea', |
|||
filterForm: '#MyDashboardFilterForm' |
|||
}); |
|||
```` |
|||
|
|||
##### Callback do Filtro |
|||
|
|||
Você pode querer ter um controle melhor para fornecer filtros ao inicializar e atualizar os widgets. Nesse caso, você pode usar a opção `filterCallback`: |
|||
|
|||
````js |
|||
var myWidgetManager = new abp.WidgetManager({ |
|||
wrapper: '#MyDashboardWidgetsArea', |
|||
filterCallback: function() { |
|||
return $('#MyDashboardFilterForm').serializeFormToObject(); |
|||
} |
|||
}); |
|||
```` |
|||
|
|||
Este exemplo mostra a implementação padrão do `filterCallback`. Você pode retornar qualquer objeto JavaScript com campos. Exemplo: |
|||
|
|||
````js |
|||
filterCallback: function() { |
|||
return { |
|||
'startDate': $('#StartDateInput').val(), |
|||
'endDate': $('#EndDateInput').val() |
|||
}; |
|||
} |
|||
```` |
|||
|
|||
Os filtros retornados são passados para todos os widgets em `init` e `refresh`. |
|||
|
|||
### API JavaScript do Widget |
|||
|
|||
Um widget pode definir uma API JavaScript que é invocada pelo `WidgetManager` quando necessário. O exemplo de código abaixo pode ser usado para começar a definir uma API para um widget. |
|||
|
|||
````js |
|||
(function () { |
|||
abp.widgets.NewUserStatisticWidget = function ($wrapper) { |
|||
|
|||
var getFilters = function () { |
|||
return { |
|||
... |
|||
}; |
|||
} |
|||
|
|||
var refresh = function (filters) { |
|||
... |
|||
}; |
|||
|
|||
var init = function (filters) { |
|||
... |
|||
}; |
|||
|
|||
return { |
|||
getFilters: getFilters, |
|||
init: init, |
|||
refresh: refresh |
|||
}; |
|||
}; |
|||
})(); |
|||
```` |
|||
|
|||
`NewUserStatisticWidget` é o nome do widget aqui. Ele deve corresponder ao nome do widget definido no lado do servidor. Todas as funções são opcionais. |
|||
|
|||
#### getFilters |
|||
|
|||
Se o widget tiver filtros personalizados internos, essa função deve retornar o objeto de filtro. Exemplo: |
|||
|
|||
````js |
|||
var getFilters = function() { |
|||
return { |
|||
frequency: $wrapper.find('.frequency-filter option:selected').val() |
|||
}; |
|||
} |
|||
```` |
|||
|
|||
Este método é usado pelo `WidgetManager` ao construir filtros. |
|||
|
|||
#### init |
|||
|
|||
Usado para inicializar o widget quando necessário. Ele tem um argumento de filtro que pode ser usado ao obter dados do servidor. O método `init` é usado quando a função `WidgetManager.init()` é chamada. Também é chamado se o seu widget requer uma recarga completa na atualização. Consulte a opção de widget `RefreshUrl`. |
|||
|
|||
#### refresh |
|||
|
|||
Usado para atualizar o widget quando necessário. Ele tem um argumento de filtro que pode ser usado ao obter dados do servidor. O método `refresh` é usado sempre que a função `WidgetManager.refresh()` é chamada. |
|||
|
|||
## Autorização |
|||
|
|||
Alguns widgets podem estar disponíveis apenas para usuários autenticados ou autorizados. Nesse caso, use as seguintes propriedades do atributo `Widget`: |
|||
|
|||
* `RequiresAuthentication` (`bool`): Defina como true para tornar este widget utilizável apenas para usuários autenticados (usuários que fizeram login na aplicação). |
|||
* `RequiredPolicies` (`List<string>`): Uma lista de nomes de políticas para autorizar o usuário. Consulte [o documento de autorização](../../Authorization.md) para obter mais informações sobre políticas. |
|||
|
|||
Exemplo: |
|||
|
|||
````csharp |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
|||
|
|||
namespace DashboardDemo.Web.Pages.Components.MySimpleWidget |
|||
{ |
|||
[Widget(RequiredPolicies = new[] { "MyPolicyName" })] |
|||
public class MySimpleWidgetViewComponent : AbpViewComponent |
|||
{ |
|||
public IViewComponentResult Invoke() |
|||
{ |
|||
return View(); |
|||
} |
|||
} |
|||
} |
|||
```` |
|||
|
|||
## WidgetOptions |
|||
|
|||
Como alternativa ao atributo `Widget`, você pode usar o `AbpWidgetOptions` para configurar widgets: |
|||
|
|||
```csharp |
|||
Configure<AbpWidgetOptions>(options => |
|||
{ |
|||
options.Widgets.Add<MySimpleWidgetViewComponent>(); |
|||
}); |
|||
``` |
|||
|
|||
Escreva isso no método `ConfigureServices` do seu [módulo](../../Module-Development-Basics.md). Todas as configurações feitas com o atributo `Widget` também são possíveis com o `AbpWidgetOptions`. Exemplo de configuração que adiciona um estilo para o widget: |
|||
|
|||
````csharp |
|||
Configure<AbpWidgetOptions>(options => |
|||
{ |
|||
options.Widgets |
|||
.Add<MySimpleWidgetViewComponent>() |
|||
.WithStyles("/Pages/Components/MySimpleWidget/Default.css"); |
|||
}); |
|||
```` |
|||
|
|||
> Dica: `AbpWidgetOptions` também pode ser usado para obter um widget existente e alterar sua configuração. Isso é especialmente útil se você deseja modificar a configuração de um widget dentro de um módulo usado por sua aplicação. Use `options.Widgets.Find` para obter uma `WidgetDefinition` existente. |
|||
|
|||
## Veja também |
|||
|
|||
* [Projeto de exemplo (código-fonte)](https://github.com/abpframework/abp-samples/tree/master/DashboardDemo). |
|||
Loading…
Reference in new issue