├── .github └── workflows │ ├── Build.yml │ └── PublishNuget.yml ├── .gitignore ├── DataInputFormScreenShot.png ├── LICENSE ├── LiquidTechnologies.Blazor.ModalDialog.sln ├── MessageBoxScreenShot.png ├── NestedModalDialogsScreenShot.png ├── README.md ├── blazor-modal-dialog.png ├── samples ├── BlazorSample │ ├── App.razor │ ├── BlazorSample.csproj │ ├── Pages │ │ ├── BackGroundCancel.razor │ │ ├── CustomStyle.razor │ │ ├── DataInputFormDemo.razor │ │ ├── HideCloseButton.razor │ │ ├── Index.razor │ │ ├── MessageBox.razor │ │ ├── Position.razor │ │ ├── ScrollableForm.razor │ │ ├── SignUpForm.razor │ │ ├── ValidationErrorForm.razor │ │ └── _Imports.razor │ ├── Program.cs │ ├── Shared │ │ ├── CustomModalLayout.razor │ │ ├── MainLayout.razor │ │ ├── NavMenu.razor │ │ └── SurveyPrompt.razor │ ├── Startup.cs │ ├── _Imports.razor │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── open-iconic │ │ │ ├── FONT-LICENSE │ │ │ ├── ICON-LICENSE │ │ │ ├── README.md │ │ │ └── font │ │ │ │ ├── css │ │ │ │ └── open-iconic-bootstrap.min.css │ │ │ │ └── fonts │ │ │ │ ├── open-iconic.eot │ │ │ │ ├── open-iconic.otf │ │ │ │ ├── open-iconic.svg │ │ │ │ ├── open-iconic.ttf │ │ │ │ └── open-iconic.woff │ │ └── site.css │ │ └── index.html └── ServerSideblazor │ ├── App.razor │ ├── Pages │ ├── BackGroundCancel.razor │ ├── CustomStyle.razor │ ├── DataInputFormDemo.razor │ ├── HideCloseButton.razor │ ├── Index.razor │ ├── MessageBox.razor │ ├── Position.razor │ ├── ScrollableForm.razor │ ├── SignUpForm.razor │ ├── ValidationErrorForm.razor │ ├── _Host.cshtml │ └── _Imports.razor │ ├── Program.cs │ ├── ServerSideblazor.csproj │ ├── Shared │ ├── CustomModalLayout.razor │ ├── MainLayout.razor │ └── NavMenu.razor │ ├── Startup.cs │ ├── _Imports.razor │ ├── appsettings.Development.json │ ├── appsettings.json │ └── wwwroot │ ├── css │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── open-iconic │ │ ├── FONT-LICENSE │ │ ├── ICON-LICENSE │ │ ├── README.md │ │ └── font │ │ │ ├── css │ │ │ └── open-iconic-bootstrap.min.css │ │ │ └── fonts │ │ │ ├── open-iconic.eot │ │ │ ├── open-iconic.otf │ │ │ ├── open-iconic.svg │ │ │ ├── open-iconic.ttf │ │ │ └── open-iconic.woff │ └── site.css │ └── favicon.ico ├── screenshot.png └── src └── LiquidTechnologies.Blazor.ModalDialog ├── Components ├── DataInputForm.razor └── MessageBoxForm.razor ├── DataInputForm └── DataInputFormField.cs ├── LiquidModalDialogJsInterop.cs ├── LiquidOpenSourcePublicKey.snk ├── LiquidTechnologies.Blazor.ModalDialog.csproj ├── MessageBox ├── MessageBoxButtons.cs ├── MessageBoxDefaultButton.cs └── MessageBoxDialogResult.cs ├── ModalDataInputForm.cs ├── ModalDialogContainer.razor ├── ModalDialogFrameView.razor ├── ModalDialogFrameView.razor.cs ├── Resources.Designer.cs ├── Resources.resx ├── ServiceCollectionExtensions.cs ├── Services ├── IModalDialogService.cs ├── ModalDialogModel.cs ├── ModalDialogOptions.cs ├── ModalDialogParameters.cs ├── ModalDialogResult.cs └── ModalDialogService.cs └── wwwroot ├── liquid-modal-dialog.css └── liquid-modal-dialog.js /.github/workflows/Build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: windows-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Setup .NET Core 13 | uses: actions/setup-dotnet@v1 14 | with: 15 | dotnet-version: 2.2.108 16 | - name: Build with dotnet 17 | run: dotnet build --configuration Release src/LiquidTechnologies.Blazor.ModalDialog/LiquidTechnologies.Blazor.ModalDialog.csproj 18 | - name: Package Release 19 | run: | 20 | cd src/LiquidTechnologies.Blazor.ModalDialog 21 | dotnet pack -c Release -o out 22 | -------------------------------------------------------------------------------- /.github/workflows/PublishNuget.yml: -------------------------------------------------------------------------------- 1 | name: Build And Publish Nuget 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: windows-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: Setup .NET Core 15 | uses: actions/setup-dotnet@v1 16 | with: 17 | dotnet-version: 2.2.108 18 | - name: Build with dotnet 19 | run: dotnet build --configuration Release src/LiquidTechnologies.Blazor.ModalDialog/LiquidTechnologies.Blazor.ModalDialog.csproj 20 | - name: Package Release 21 | run: | 22 | cd src/LiquidTechnologies.Blazor.ModalDialog 23 | dotnet pack -c Release -o out 24 | - name: Publish Nuget to registry 25 | run: dotnet nuget push .\src\LiquidTechnologies.Blazor.ModalDialog\out\*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://www.nuget.org/api/v2/package 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /DataInputFormScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/DataInputFormScreenShot.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright © 2001-2019 Liquid Technologies Limited. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LiquidTechnologies.Blazor.ModalDialog.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28531.58 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiquidTechnologies.Blazor.ModalDialog", "src\LiquidTechnologies.Blazor.ModalDialog\LiquidTechnologies.Blazor.ModalDialog.csproj", "{997CB0B4-2B3F-4625-9259-A560CD82AC8C}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{AC842EAA-F630-4597-A0FC-6758FE9F6268}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorSample", "samples\BlazorSample\BlazorSample.csproj", "{4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerSideblazor", "samples\ServerSideblazor\ServerSideblazor.csproj", "{6290EEF7-69B6-43D0-8FA9-999045336637}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E8AD9151-AB7E-4531-A1DF-8952B1D5580D}" 15 | ProjectSection(SolutionItems) = preProject 16 | README.md = README.md 17 | EndProjectSection 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Debug|x64 = Debug|x64 23 | Debug|x86 = Debug|x86 24 | Release|Any CPU = Release|Any CPU 25 | Release|x64 = Release|x64 26 | Release|x86 = Release|x86 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Debug|x64.ActiveCfg = Debug|Any CPU 32 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Debug|x64.Build.0 = Debug|Any CPU 33 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Debug|x86.ActiveCfg = Debug|Any CPU 34 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Debug|x86.Build.0 = Debug|Any CPU 35 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Release|x64.ActiveCfg = Release|Any CPU 38 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Release|x64.Build.0 = Release|Any CPU 39 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Release|x86.ActiveCfg = Release|Any CPU 40 | {997CB0B4-2B3F-4625-9259-A560CD82AC8C}.Release|x86.Build.0 = Release|Any CPU 41 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Debug|x64.ActiveCfg = Debug|Any CPU 44 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Debug|x64.Build.0 = Debug|Any CPU 45 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Debug|x86.ActiveCfg = Debug|Any CPU 46 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Debug|x86.Build.0 = Debug|Any CPU 47 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Release|x64.ActiveCfg = Release|Any CPU 50 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Release|x64.Build.0 = Release|Any CPU 51 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Release|x86.ActiveCfg = Release|Any CPU 52 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D}.Release|x86.Build.0 = Release|Any CPU 53 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 54 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Debug|Any CPU.Build.0 = Debug|Any CPU 55 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Debug|x64.ActiveCfg = Debug|Any CPU 56 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Debug|x64.Build.0 = Debug|Any CPU 57 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Debug|x86.ActiveCfg = Debug|Any CPU 58 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Debug|x86.Build.0 = Debug|Any CPU 59 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Release|Any CPU.ActiveCfg = Release|Any CPU 60 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Release|Any CPU.Build.0 = Release|Any CPU 61 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Release|x64.ActiveCfg = Release|Any CPU 62 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Release|x64.Build.0 = Release|Any CPU 63 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Release|x86.ActiveCfg = Release|Any CPU 64 | {6290EEF7-69B6-43D0-8FA9-999045336637}.Release|x86.Build.0 = Release|Any CPU 65 | EndGlobalSection 66 | GlobalSection(SolutionProperties) = preSolution 67 | HideSolutionNode = FALSE 68 | EndGlobalSection 69 | GlobalSection(NestedProjects) = preSolution 70 | {4ECB8E84-B0FF-4DC0-9929-D0BE5922E97D} = {AC842EAA-F630-4597-A0FC-6758FE9F6268} 71 | {6290EEF7-69B6-43D0-8FA9-999045336637} = {AC842EAA-F630-4597-A0FC-6758FE9F6268} 72 | EndGlobalSection 73 | GlobalSection(ExtensibilityGlobals) = postSolution 74 | SolutionGuid = {FB2D90F4-21CF-4118-82E7-479E89C15FB3} 75 | EndGlobalSection 76 | EndGlobal 77 | -------------------------------------------------------------------------------- /MessageBoxScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/MessageBoxScreenShot.png -------------------------------------------------------------------------------- /NestedModalDialogsScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/NestedModalDialogsScreenShot.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Liquid Technologies Modal Dialogs for Blazor 2 | 3 | A simple and customizable Modal Dialog and MessageBox implementation for [Blazor](https://blazor.net) 4 | 5 | ![Screenshot of the component in action](screenshot.png) 6 | 7 | ## Summary 8 | * Simple way to turn a Blazor Component into a Modal Dialog. 9 | * Data can be passed to the Modal Dialog Blazor Component 10 | * Allows values returned from the Modal Dialog Blazor Component to be retrieved. 11 | * Can be used in functions without breaking up the flow of the logic i.e. 12 | ``` 13 | ModalDialogResult result = await ModalDialog.ShowDialogAsync("Are You Sure"); 14 | if (result.Success) 15 | DeleteEverything(); 16 | ``` 17 | * Can be nested. i.e. a Modal Dialog can create child Modal Dialogs. 18 | * Includes Simple Windows style MessageBox's 19 | 20 | 21 | 22 | ## Credits 23 | 24 | This is a re-work of Chris Sainty's [Blazored.Modal](https://github.com/Blazored/Modal), it builds on the work he has done, but because the approach is quite different and the API is not compatible, I chose to re-package this as a separate project. All namespaces and CSS styles names have been altered to avoid clashes. 25 | 26 | 27 | ## Getting Setup 28 | 29 | You can install the package via the nuget package manager just search for *LiquidTechnologies.Blazor.ModalDialog*. You can also install via powershell using the following command. 30 | 31 | ```powershell 32 | Install-Package LiquidTechnologies.Blazor.ModalDialog 33 | ``` 34 | 35 | Or via the dotnet CLI. 36 | 37 | ```bash 38 | dotnet add package LiquidTechnologies.Blazor.ModalDialog 39 | ``` 40 | 41 | ### 1. Register Services 42 | 43 | You will need to add the following using statement and add a call to register the Blazored Modal services in your applications `Startup.ConfigureServices` method. 44 | 45 | ```csharp 46 | using Blazor.ModalDialog; 47 | 48 | public void ConfigureServices(IServiceCollection services) 49 | { 50 | services.AddModalDialog(); 51 | } 52 | ``` 53 | 54 | ### 2. Add Imports 55 | 56 | Add the following to your *_Imports.razor* 57 | 58 | ```csharp 59 | @using Blazor.ModalDialog 60 | ``` 61 | 62 | ### 3. Add Modal Component 63 | 64 | Add the `` tag into your applications *MainLayout.razor*. 65 | 66 | ### 4. Add reference to stylesheet and .js 67 | 68 | Add the following line to the `head` tag of your `_Host.cshtml` (Blazor Server app). 69 | 70 | In the `` 71 | ```html 72 | 73 | ``` 74 | At the bottom of the `` 75 | ```html 76 | 77 | ``` 78 | 79 | 80 | 81 | ## Usage 82 | 83 | ### Showing a Dialog and getting the return value 84 | 85 | In order to show the modal, you have to inject the `IModalDialogService` into the component or service you want to invoke the modal. 86 | You can then call the `ShowDialogAsync` method passing in the title for the modal and the type of the component you want the modal to display. 87 | 88 | For example, say I have a component called `SignUpForm` which will request the users first and last name. 89 | 90 | Once the user has completed the form a ModalDialogResult object is returned with the result. 91 | The data the user submitted in the form can then be read and used (or ignored if the form was cancelled). 92 | 93 | ```html 94 | @page "/" 95 | @inject IModalDialogService ModalDialog 96 | 97 | 98 | 99 | @code { 100 | async void SignUpBtn_Clicked() 101 | { 102 | ModalDialogResult result = await ModalDialog.ShowDialogAsync("Sign Up For your free account"); 103 | if (result.Success) 104 | CreateNewUser(result.ReturnParameters.Get("FirstName"), result.ReturnParameters.Get("LastName")) 105 | } 106 | } 107 | ``` 108 | **Note** *the function `SignUpBtn_Clicked` is `async`. The Task returned from `ModalDialog.ShowDialogAsync` is only completed when the SignUpForm has been closed, allowing the code to make use of the return values from the Modal Dialog.* 109 | 110 | ### Passing Arguments to a Dialog 111 | 112 | If you need to pass values to the component you are displaying in the modal dialog, then you can use the `ModalDialogParameters` object. 113 | The parameters added to the `ModalDialogParameters` object will be used to set the `[Parameter]` values on the component, in addition a 114 | `[CascadingParameter]` is also added containing the `ModalDialogParameters` object. 115 | 116 | ```html 117 | @page "/" 118 | @inject IModalDialogService ModalDialog 119 | 120 |

My Movies

121 | 122 |
    123 | @foreach (var movie in Movies) 124 | { 125 |
  • @movie.Name (@movie.Year) -
  • 126 | } 127 |
128 | 129 | @code { 130 | 131 | List Movies { get; set; } 132 | 133 | async void ShowEditMovie(int movieId) 134 | { 135 | ModalDialogParameters parameters = new ModalDialogParameters(); 136 | parameters.Add("MovieId", movieId); 137 | 138 | Movie editedMovie = await ModalDialog.ShowDialogAsync("Edit Movie", new ModalDialogOptions(), parameters); 139 | } 140 | } 141 | ``` 142 | 143 | ### Options 144 | 145 | ```html 146 | @inject IMovieService MovieService 147 | @inject IModalDialogService ModalDialogService 148 | 149 |
150 | 151 |
152 | 153 | 154 |
155 | 156 |
157 | 158 | 159 |
160 | 161 | 162 | 163 |
164 | 165 | @code { 166 | 167 | [Parameter] 168 | public int MovieId { get; set; } 169 | 170 | Movie Movie { get; set; } 171 | 172 | protected override void OnInit() 173 | { 174 | LoadMovie(MovieId); 175 | } 176 | 177 | void LoadMovie(int movieId) 178 | { 179 | Movie = MovieService.Load(movieId); 180 | } 181 | 182 | void SaveMovie() 183 | { 184 | MovieService.Save(Movie); 185 | 186 | ModalDialogParameters returnParameters = new ModalDialogParameters(); 187 | returnParameters.Add("Movie", Movie); 188 | ModalDialogService.Close(true, returnParameters); 189 | } 190 | 191 | void Cancel() 192 | { 193 | ModalDialogService.Close(false); 194 | } 195 | } 196 | ``` 197 | 198 | ### Options 199 | 200 | The modal dialogs can be customized to fit a wide variety of uses. These options can be set using the `ModalDialogOptions` object passed into `ShowDialogAsync`. 201 | 202 | #### Hiding the close button 203 | 204 | A modal has a close button in the top right hand corner by default. 205 | 206 | ```csharp 207 | @code { 208 | void ShowModal() 209 | { 210 | ModalDialogOptions options = new ModalDialogOptions() 211 | { 212 | ShowCloseButton = false 213 | }; 214 | 215 | await ModalDialog.ShowDialogAsync("My Movies", options); 216 | } 217 | } 218 | ``` 219 | 220 | #### Disabling background click cancellation 221 | 222 | You can disable canceling the modal by clicking on the background using the `BackgroundClickToClose` parameter. 223 | 224 | ```csharp 225 | @code { 226 | void ShowModal() 227 | { 228 | ModalDialogOptions options = new ModalDialogOptions() 229 | { 230 | BackgroundClickToClose = false 231 | }; 232 | 233 | await ModalDialog.ShowDialogAsync("My Movies", options); 234 | } 235 | } 236 | ``` 237 | 238 | #### Styling the modal 239 | 240 | You can set an alternative CSS style for the modal if you want to customize the look and feel. 241 | This is useful when your web application requires different kinds of modal dialogs, like a warning, confirmation or an input form. 242 | 243 | ```csharp 244 | @code { 245 | void ShowModal() 246 | { 247 | ModalDialogOptions options = new ModalDialogOptions() 248 | { 249 | Style = "acme-modal-dialog-movies" 250 | }; 251 | 252 | await ModalDialog.ShowDialogAsync("My Movies", options); 253 | } 254 | } 255 | ``` 256 | 257 | #### Setting the position 258 | 259 | Modal Dialogs are shown in the center of the viewport by default. The modal can be shown in different positions if needed. The positioning is flexible as it is set using CSS styling. 260 | 261 | The following positioning styles are available out of the box: `liquid-modal-dialog-center`, `liquid-modal-dialog-topleft`, `liquid-modal-dialog-topright`, `liquid-modal-dialog-bottomleft` and `liquid-modal-dialog-bottomright`. Definitions of these styles are found in `ModalDialogPositionOptions`. 262 | 263 | 264 | ```csharp 265 | @code { 266 | void ShowModal() 267 | { 268 | ModalDialogOptions options = new ModalDialogOptions() 269 | { 270 | Position = ModalDialogPositionOptions.TopLeft 271 | }; 272 | 273 | await ModalDialog.ShowDialogAsync("My Movies", options); 274 | } 275 | } 276 | ``` 277 | 278 | ### Error Handling 279 | 280 | ```csharp 281 | // Opeing the Dialog 282 | try 283 | { 284 | ModalDialogResult result = await ModalDialog.ShowDialogAsync("Sign Up Form"); 285 | if (result.Success) 286 | Message = "New User Created : " + result.ReturnParameters.Get("UserID"); 287 | } 288 | catch(Exception ex) 289 | { 290 | // Handle Exception thrown from ShowDialogAsync 291 | } 292 | 293 | ... 294 | 295 | // In the Blazor Component 296 | async void Ok_Clicked() 297 | { 298 | try 299 | { 300 | int newUserID = CreateUser(FirstName, LastName); 301 | 302 | ModalDialogParameters resultParameters = new ModalDialogParameters(); 303 | resultParameters.Set("UserID", newUserID); 304 | ModalDialogService.Close(true, resultParameters); 305 | } 306 | catch (Exception ex) 307 | { 308 | // pass the exception back to the ShowDialogAsync call that opened the Dialog 309 | ModalDialogService.Close(ex); 310 | } 311 | } 312 | 313 | ``` 314 | 315 | ### Nested Modal Dialogs 316 | 317 | When a Modal Dialog is displayed it is possible to display another Modal Dialog over the top. there is no limit to the number of dialogs that can be displayed in this way (MessageBoxes can also be used while Modal Dialogs are shown). 318 | 319 | ![Screenshot of the nested Modal Dialogs](NestedModalDialogsScreenShot.png) 320 | 321 | ### MessageBoxes 322 | 323 | For convenience a set of Windows style Message Box's can be created using the `ShowMessageBoxAsync` method. These work in the same ways as the standard Windows MessageBox (except it doesn't have an icon). 324 | 325 | `Task IModalDialogService.ShowMessageBoxAsync(string title, string message, MessageBoxButtons buttons = MessageBoxButtons.OK, MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1)` 326 | 327 | They can be used as 328 | 329 | ```csharp 330 | async void DeleteAllFilesButton_Clicked() 331 | { 332 | MessageBoxDialogResult result = await ModalDialog.ShowMessageBoxAsync("Confirm Delete", "Are you sure you want to delete all the files?", MessageBoxButtons.YesNo, MessageBoxDefaultButton.Button2); 333 | if (result == MessageBoxDialogResult.No) 334 | return; 335 | 336 | DeleteAllFiles(); 337 | } 338 | ``` 339 | 340 | 341 | ![Screenshot of the MessageBox](MessageBoxScreenShot.png) 342 | 343 | 344 | 345 | ### Simple Data Input Form 346 | 347 | The ModalDataInputForm makes it possible to construct simple data input forms for capturing and editing 348 | basic information without the need to create a specific razor component to handle it. 349 | 350 | Simply create a ModalDataInputForm instance, and add the fields you need to it. Then call ShowAsync, 351 | when the user submits the form the data is returned in the fields you just created. 352 | 353 | ![Screenshot of the Blazor Data Input Form](DataInputFormScreenShot.png) 354 | 355 | #### Features 356 | * Field Type Support 357 | * String 358 | * Integer 359 | * Boolean 360 | * Enumerations 361 | * Field properties 362 | * custom validation function 363 | * min/max length 364 | * min/max value 365 | * auto trucate 366 | * auto trim 367 | * custom validation function 368 | * Validation 369 | * Field level 370 | * Cross Field validation 371 | 372 | #### Sample Code 373 | 374 | ```csharp 375 | 376 | @@inject IModalDialogService ModalService 377 | 378 | ... 379 | 380 | @@code 381 | { 382 | enum GenderType { Male, Female } 383 | 384 | private string Name = "Fred"; 385 | private GenderType Gender = GenderType.Male; 386 | private int Age = 25; 387 | private bool Married = false; 388 | 389 | 390 | async void Edit_Clicked() 391 | { 392 | ModalDataInputForm frm = new ModalDataInputForm("Edit Data", "A description of the data"); 393 | 394 | var nameFld = frm.AddStringField("Name", "First Name", this.Name, "the users first name"); 395 | var genderFld = frm.AddEnumField("Gender", "Sex", this.Gender, "the users gender"); 396 | var ageFld = frm.AddIntField("Age", "Age", this.Age, "the age of the user", min:0, max:130); 397 | var marriedFld = frm.AddBoolField("Married", "Is Married", this.Married, "is the user married"); 398 | 399 | if (await frm.ShowAsync(ModalService)) 400 | { 401 | this.Name = nameFld.Value; 402 | this.Gender = genderFld.Value; 403 | this.Age = ageFld.Value; 404 | this.Married = marriedFld.Value; 405 | StateHasChanged(); 406 | } 407 | } 408 | } 409 | ``` 410 | -------------------------------------------------------------------------------- /blazor-modal-dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/blazor-modal-dialog.png -------------------------------------------------------------------------------- /samples/BlazorSample/App.razor: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 |

Page not found

11 |

Sorry, but there's nothing here!

12 |
13 |
-------------------------------------------------------------------------------- /samples/BlazorSample/BlazorSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; 7 | https://dotnet.myget.org/F/blazor-dev/api/v3/index.json; 8 | 9 | 7.3 10 | 3.0 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/BackGroundCancel.razor: -------------------------------------------------------------------------------- 1 | @page "/backgroundcancel" 2 | @inject IModalDialogService ModalDialog 3 | 4 |

Click background to cancel

5 | 6 |
7 | 8 |

9 | A modal is cancelled by default if the user clicks outside the modal. This behavior can 10 | be disabled. 11 |

12 | 13 | 14 | 15 | @code { 16 | 17 | void BackgroundCancelEnabled() 18 | { 19 | var parameters = new ModalDialogParameters(); 20 | parameters.Add("FormId", 11); 21 | var options = new ModalDialogOptions() { BackgroundClickToClose = true }; 22 | 23 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 24 | } 25 | 26 | void BackgroundCancelDisabled() 27 | { 28 | var parameters = new ModalDialogParameters(); 29 | parameters.Add("FormId", 11); 30 | var options = new ModalDialogOptions() { BackgroundClickToClose = false }; 31 | 32 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/CustomStyle.razor: -------------------------------------------------------------------------------- 1 | @page "/custom" 2 | @inject IModalDialogService ModalDialog 3 | @layout CustomModalLayout 4 | 5 |

Liquid Technologies Modal Dialog Sample with Custom Styling

6 | 7 |
8 |

9 | A custom style can also be set as a parameter on the Modal.Show() method. 10 |

11 | 12 | 13 |
14 |

15 | The same dialog with the default styling: 16 |

17 | 18 | 19 | 20 | @code { 21 | 22 | void ShowModalCustomStyle() 23 | { 24 | var options = new ModalDialogOptions() { Style = "liquid-prompt-modal" }; 25 | 26 | ModalDialog.ShowDialogAsync("Delete record?", options); 27 | } 28 | 29 | void ShowModal() 30 | { 31 | ModalDialog.ShowDialogAsync("Delete record?"); 32 | } 33 | } -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/DataInputFormDemo.razor: -------------------------------------------------------------------------------- 1 | @page "/datainputformdemo" 2 | @inject IModalDialogService ModalService 3 | 4 |

Liquid Technologies Modal Dialog Sample

5 | 6 |
7 | 8 |

9 | This example also show how to quickly create data entry forms. 10 |

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Name@Name
Gender@Gender
Age@Age
Married@Married
32 | 33 | 34 | 35 | 36 |
37 | 38 |

Sample Code

39 |
 40 | @@inject IModalDialogService ModalService
 41 | 
 42 | ...
 43 | 
 44 | @@code 
 45 | {
 46 |     enum GenderType { Male, Female }
 47 | 
 48 |     private string Name = "Fred";
 49 |     private GenderType Gender = GenderType.Male;
 50 |     private int Age = 25;
 51 |     private bool Married = false;
 52 | 
 53 | 
 54 |     async void Edit_Clicked()
 55 |     {
 56 |         ModalDataInputForm frm = new ModalDataInputForm("Edit Data", "A description of the data");
 57 | 
 58 |         var nameFld = frm.AddStringField("Name", "First Name", this.Name, "the users first name");
 59 |         var genderFld = frm.AddEnumField<GenderType>("Gender", "Sex", this.Gender, "the users gender");
 60 |         var ageFld = frm.AddIntField("Age", "Age", this.Age, "the age of the user", min:0, max:130);
 61 |         var marriedFld = frm.AddBoolField("Married", "Is Married", this.Married, "is the user married");
 62 | 
 63 |         if (await frm.ShowAsync(ModalService))
 64 |         {
 65 |             this.Name = nameFld.Value;
 66 |             this.Gender = genderFld.Value;
 67 |             this.Age = ageFld.Value;
 68 |             this.Married = marriedFld.Value;
 69 |             StateHasChanged();
 70 |         }
 71 |     }
 72 | }
 73 | 
74 | 75 | @code { 76 | 77 | enum GenderType { Male, Female } 78 | 79 | private string Name = "Fred"; 80 | private GenderType Gender = GenderType.Male; 81 | private int Age = 25; 82 | private bool Married = false; 83 | 84 | 85 | async void Edit_Clicked() 86 | { 87 | ModalDataInputForm frm = new ModalDataInputForm("Edit Data", "A description of the data"); 88 | 89 | var nameFld = frm.AddStringField("Name", "First Name", this.Name, "the users first name"); 90 | var genderFld = frm.AddEnumField("Gender", "Sex", this.Gender, "the users gender"); 91 | var ageFld = frm.AddIntField("Age", "Age", this.Age, "the age of the user", min: 0, max: 130); 92 | var marriedFld = frm.AddBoolField("Married", "Is Married", this.Married, "is the user married"); 93 | 94 | if (await frm.ShowAsync(ModalService)) 95 | { 96 | this.Name = nameFld.Value; 97 | this.Gender = genderFld.Value; 98 | this.Age = ageFld.Value; 99 | this.Married = marriedFld.Value; 100 | StateHasChanged(); 101 | } 102 | } 103 | } 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/HideCloseButton.razor: -------------------------------------------------------------------------------- 1 | @page "/closebutton" 2 | @inject IModalDialogService ModalDialog 3 | 4 |

Hiding the modal close button

5 | 6 |
7 | 8 |

9 | Liquid Technologies Modal Dialog shows a close button in the modal by default. The button can be hidden if you 10 | prefer to handle closing the modal yourself. 11 |

12 | 13 | 14 | 15 | 16 | @code { 17 | 18 | void CloseButtonShown() 19 | { 20 | var parameters = new ModalDialogParameters(); 21 | parameters.Add("FormId", 11); 22 | 23 | var options = new ModalDialogOptions() { ShowCloseButton = true }; 24 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 25 | } 26 | 27 | void CloseButtonHidden() 28 | { 29 | var parameters = new ModalDialogParameters(); 30 | parameters.Add("FormId", 11); 31 | 32 | var options = new ModalDialogOptions() { ShowCloseButton = false }; 33 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @inject IModalDialogService ModalDialog 3 | 4 |

Liquid Technologies Modal Dialog Sample

5 | 6 |
7 | 8 |

9 | This example shows how a ModalDialog can be incorporated into the 10 | logical flow of an async function, and how data can be passed to 11 | and retrieved. 12 |

13 | 14 |
15 | 
16 |     async void ShowModal()
17 |     {
18 |         // Arguments can be passed into the modal dialog
19 |         var parameters = new ModalDialogParameters();
20 |         parameters.Add("FormId", 11);
21 | 
22 |         // using await will cause execution to resume when the dialog has been closed.
23 |         ModalDialogResult result = await ModalDialog.ShowDialogAsync<SignUpForm>("Sign Up Form", null, parameters);
24 |         if (result.Success)
25 |             Message = "User Provided the value : " + result.ReturnParameters.Get<string>("FullName");
26 |         else
27 |             Message = "User Cancelled";
28 |     }
29 | 
30 | 31 |

32 | This example also show the ability to nest dialog boxes, for examples 33 | if you submit the popup form without populating any data, a confirmation 34 | dialog is shown over the top of the active dialog. 35 |

36 | 37 | 38 | 39 |

@Message

40 | 41 | @code { 42 | string Message = ""; 43 | 44 | 45 | async void ShowModal() 46 | { 47 | Message = "Requesting Data From User"; 48 | StateHasChanged(); 49 | 50 | var parameters = new ModalDialogParameters(); 51 | parameters.Add("FormId", 11); 52 | ModalDialogResult result = await ModalDialog.ShowDialogAsync("Sign Up Form", null, parameters); 53 | if (result.Success) 54 | Message = "User Provided the value : " + result.ReturnParameters.Get("FullName"); 55 | else 56 | Message = "User Cancelled"; 57 | StateHasChanged(); 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/MessageBox.razor: -------------------------------------------------------------------------------- 1 | @page "/messagebox" 2 | @inject IModalDialogService ModalDialog 3 | 4 |

Liquid Technologies Modal Dialog Sample MessageBox's

5 | 6 |
7 | 8 |

9 | Shows how basic MessageBoxes can be displayed: 10 |

11 |

12 | 13 |

14 |

15 | 16 |

17 |

18 | 19 |

20 |

21 | 22 |

23 | 24 |
25 | Last Message box result : @LastMessageBoxResult 26 |
27 | 28 | @code { 29 | 30 | string LastMessageBoxResult = "Not Set"; 31 | 32 | async void ShowMessageBoxOK() 33 | { 34 | MessageBoxDialogResult result = await ModalDialog.ShowMessageBoxAsync("Simple Message Box", "Click OK, the close button or the background to Close", MessageBoxButtons.OK, MessageBoxDefaultButton.Button1); 35 | 36 | LastMessageBoxResult = result.ToString(); 37 | StateHasChanged(); 38 | } 39 | 40 | async void ShowMessageBoxYesNoCancel() 41 | { 42 | MessageBoxDialogResult result = await ModalDialog.ShowMessageBoxAsync("Yes/No/Cancel Message Box", "Clicking the close button or the background is equivient to the Cancel button. Setting the default button to Button2 causes the 'No' button to be highlighted.", MessageBoxButtons.YesNoCancel, MessageBoxDefaultButton.Button2); 43 | LastMessageBoxResult = result.ToString(); 44 | StateHasChanged(); 45 | } 46 | 47 | async void ShowMessageBoxYesNo() 48 | { 49 | MessageBoxDialogResult result = await ModalDialog.ShowMessageBoxAsync("Yes/No Message Box", "Requires the Yes/No button to be pressed, can't be dismissed with the close or clicking in the background", MessageBoxButtons.YesNo, MessageBoxDefaultButton.Button2); 50 | LastMessageBoxResult = result.ToString(); 51 | StateHasChanged(); 52 | } 53 | 54 | async void ShowMessageBoxAbortRetryIgnore() 55 | { 56 | MessageBoxDialogResult result = await ModalDialog.ShowMessageBoxAsync("Abort/Retry/Ignore Message Box", "Requires the Abort/Retry/Ignore button to be pressed, can't be dismissed with the close or clicking in the background", MessageBoxButtons.AbortRetryIgnore, MessageBoxDefaultButton.Button3); 57 | LastMessageBoxResult = result.ToString(); 58 | StateHasChanged(); 59 | } 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/Position.razor: -------------------------------------------------------------------------------- 1 | @page "/position" 2 | @inject IModalDialogService ModalDialog 3 | 4 |

Positioning the modal

5 | 6 |
7 | 8 |

9 | The modal is shown in the center of the viewport by default. The modal can be shown 10 | in different positions if needed. The positioning is flexible as it is set using 11 | CSS styling. 12 |

13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | @code { 21 | 22 | void PositionCenter() 23 | { 24 | var parameters = new ModalDialogParameters(); 25 | parameters.Add("FormId", 11); 26 | 27 | ModalDialog.ShowDialogAsync("Sign Up Form", null, parameters); 28 | } 29 | 30 | void PositionCustom(string position) 31 | { 32 | var parameters = new ModalDialogParameters(); 33 | parameters.Add("FormId", 11); 34 | var options = new ModalDialogOptions() { Position = position }; 35 | 36 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/ScrollableForm.razor: -------------------------------------------------------------------------------- 1 | @page "/scrollableform" 2 | @inject IModalDialogService ModalService 3 | 4 |

Liquid Technologies Modal Dialog Sample

5 | 6 |
7 | 8 |

9 | This example also show how the form displays the form when it contains to much information for the screen. 10 |

11 | 12 | 13 | 14 |
15 | 16 |

Sample Code

17 |
18 | @@inject IModalDialogService ModalService
19 | 
20 | ...
21 | 
22 | @@code {
23 | 
24 |     async void Edit_Clicked()
25 |     {
26 |         ModalDataInputForm frm = new ModalDataInputForm("Edit Data", "When the fields are to big to fit on the form");
27 | 
28 |         for(int i=0;i<30;i++)
29 |             frm.AddStringField($"Field{i}", $"Field {i}", $"Value {i}", $"Field {i}");
30 | 
31 |         await frm.ShowAsync(ModalService);
32 |     }
33 | }
34 | 
35 | 36 | @code { 37 | 38 | async void Edit_Clicked() 39 | { 40 | ModalDataInputForm frm = new ModalDataInputForm("Edit Data", "When the fields are to big to fit on the form"); 41 | 42 | for(int i=0;i<30;i++) 43 | frm.AddStringField($"Field{i}", $"Field {i}", $"Value {i}", $"Field {i}"); 44 | 45 | await frm.ShowAsync(ModalService); 46 | } 47 | } 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/SignUpForm.razor: -------------------------------------------------------------------------------- 1 | @inject IModalDialogService ModalDialogService 2 | 3 |

Form Id input Parameter : @FormId

4 | 5 |
6 | 7 |
8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 | 19 |
20 | 21 | 22 | @code { 23 | 24 | [Parameter] 25 | public string FirstName { get; set; } 26 | [Parameter] 27 | public string LastName { get; set; } 28 | [Parameter] 29 | public int FormId { get; set; } 30 | 31 | async void Ok_Clicked() 32 | { 33 | if (string.IsNullOrWhiteSpace(FirstName) && string.IsNullOrWhiteSpace(LastName)) 34 | { 35 | ModalDialogResult result = await ModalDialogService.ShowDialogAsync("Validation Errors"); 36 | if (result.Success == false) 37 | ModalDialogService.Close(false); 38 | } 39 | else 40 | { 41 | ModalDialogParameters resultParameters = new ModalDialogParameters(); 42 | resultParameters.Set("FirstName", FirstName); 43 | resultParameters.Set("LastName", LastName); 44 | resultParameters.Set("FullName", FirstName + " " + LastName); 45 | ModalDialogService.Close(true, resultParameters); 46 | } 47 | } 48 | 49 | void Cancel_Clicked() 50 | { 51 | ModalDialogService.Close(false); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/ValidationErrorForm.razor: -------------------------------------------------------------------------------- 1 | @inject IModalDialogService ModalDialogService 2 | 3 |
4 |
5 |

The data you have entered is incomplete or contains errors.

6 |

This demonstrates using nested dialogs, i.e. the Errors dialog over the SignUp form

7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | @code { 15 | 16 | void Retry_Clicked() 17 | { 18 | ModalDialogService.Close(true); 19 | } 20 | 21 | void Cancel_Clicked() 22 | { 23 | ModalDialogService.Close(false); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/BlazorSample/Pages/_Imports.razor: -------------------------------------------------------------------------------- 1 | @layout MainLayout 2 | -------------------------------------------------------------------------------- /samples/BlazorSample/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Blazor.Hosting; 2 | 3 | namespace BlazorSample 4 | { 5 | public class Program 6 | { 7 | public static void Main(string[] args) 8 | { 9 | CreateHostBuilder(args).Build().Run(); 10 | } 11 | 12 | public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) => 13 | BlazorWebAssemblyHost.CreateDefaultBuilder() 14 | .UseBlazorStartup(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/BlazorSample/Shared/CustomModalLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 4 | 5 | 8 | 9 |
10 |
11 | About 12 |
13 | 14 |
15 | @Body 16 |
17 |
18 | -------------------------------------------------------------------------------- /samples/BlazorSample/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 4 | 5 | 8 | 9 |
10 |
11 | About 12 |
13 | 14 |
15 | @Body 16 |
17 |
18 | -------------------------------------------------------------------------------- /samples/BlazorSample/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  7 | 8 |
9 | 37 |
38 | 39 | @code { 40 | bool collapseNavMenu = true; 41 | 42 | void ToggleNavMenu() 43 | { 44 | collapseNavMenu = !collapseNavMenu; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /samples/BlazorSample/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 |  11 | 12 | @code { 13 | [Parameter] public string Title { get; set; } // Demonstrates how a parent component can supply parameters 14 | } 15 | -------------------------------------------------------------------------------- /samples/BlazorSample/Startup.cs: -------------------------------------------------------------------------------- 1 | using Blazor.ModalDialog; 2 | using Microsoft.AspNetCore.Components.Builder; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace BlazorSample 6 | { 7 | public class Startup 8 | { 9 | public void ConfigureServices(IServiceCollection services) 10 | { 11 | services.AddModalDialog(); 12 | } 13 | 14 | public void Configure(IComponentsApplicationBuilder app) 15 | { 16 | app.AddComponent("app"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /samples/BlazorSample/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Components.Routing 3 | @using Microsoft.AspNetCore.Components.Web 4 | @using Microsoft.JSInterop 5 | @using BlazorSample 6 | @using BlazorSample.Shared 7 | 8 | @using Blazor.ModalDialog 9 | -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/css/open-iconic/FONT-LICENSE: -------------------------------------------------------------------------------- 1 | SIL OPEN FONT LICENSE Version 1.1 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | PREAMBLE 6 | The goals of the Open Font License (OFL) are to stimulate worldwide 7 | development of collaborative font projects, to support the font creation 8 | efforts of academic and linguistic communities, and to provide a free and 9 | open framework in which fonts may be shared and improved in partnership 10 | with others. 11 | 12 | The OFL allows the licensed fonts to be used, studied, modified and 13 | redistributed freely as long as they are not sold by themselves. The 14 | fonts, including any derivative works, can be bundled, embedded, 15 | redistributed and/or sold with any software provided that any reserved 16 | names are not used by derivative works. The fonts and derivatives, 17 | however, cannot be released under any other type of license. The 18 | requirement for fonts to remain under this license does not apply 19 | to any document created using the fonts or their derivatives. 20 | 21 | DEFINITIONS 22 | "Font Software" refers to the set of files released by the Copyright 23 | Holder(s) under this license and clearly marked as such. This may 24 | include source files, build scripts and documentation. 25 | 26 | "Reserved Font Name" refers to any names specified as such after the 27 | copyright statement(s). 28 | 29 | "Original Version" refers to the collection of Font Software components as 30 | distributed by the Copyright Holder(s). 31 | 32 | "Modified Version" refers to any derivative made by adding to, deleting, 33 | or substituting -- in part or in whole -- any of the components of the 34 | Original Version, by changing formats or by porting the Font Software to a 35 | new environment. 36 | 37 | "Author" refers to any designer, engineer, programmer, technical 38 | writer or other person who contributed to the Font Software. 39 | 40 | PERMISSION & CONDITIONS 41 | Permission is hereby granted, free of charge, to any person obtaining 42 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 43 | redistribute, and sell modified and unmodified copies of the Font 44 | Software, subject to the following conditions: 45 | 46 | 1) Neither the Font Software nor any of its individual components, 47 | in Original or Modified Versions, may be sold by itself. 48 | 49 | 2) Original or Modified Versions of the Font Software may be bundled, 50 | redistributed and/or sold with any software, provided that each copy 51 | contains the above copyright notice and this license. These can be 52 | included either as stand-alone text files, human-readable headers or 53 | in the appropriate machine-readable metadata fields within text or 54 | binary files as long as those fields can be easily viewed by the user. 55 | 56 | 3) No Modified Version of the Font Software may use the Reserved Font 57 | Name(s) unless explicit written permission is granted by the corresponding 58 | Copyright Holder. This restriction only applies to the primary font name as 59 | presented to the users. 60 | 61 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 62 | Software shall not be used to promote, endorse or advertise any 63 | Modified Version, except to acknowledge the contribution(s) of the 64 | Copyright Holder(s) and the Author(s) or with their explicit written 65 | permission. 66 | 67 | 5) The Font Software, modified or unmodified, in part or in whole, 68 | must be distributed entirely under this license, and must not be 69 | distributed under any other license. The requirement for fonts to 70 | remain under this license does not apply to any document created 71 | using the Font Software. 72 | 73 | TERMINATION 74 | This license becomes null and void if any of the above conditions are 75 | not met. 76 | 77 | DISCLAIMER 78 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 79 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 80 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 81 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 82 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 83 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 84 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 85 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 86 | OTHER DEALINGS IN THE FONT SOFTWARE. 87 | -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/css/open-iconic/README.md: -------------------------------------------------------------------------------- 1 | [Open Iconic v1.1.1](http://useiconic.com/open) 2 | =========== 3 | 4 | ### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons) 5 | 6 | 7 | 8 | ## What's in Open Iconic? 9 | 10 | * 223 icons designed to be legible down to 8 pixels 11 | * Super-light SVG files - 61.8 for the entire set 12 | * SVG sprite—the modern replacement for icon fonts 13 | * Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats 14 | * Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats 15 | * PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px. 16 | 17 | 18 | ## Getting Started 19 | 20 | #### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections. 21 | 22 | ### General Usage 23 | 24 | #### Using Open Iconic's SVGs 25 | 26 | We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute). 27 | 28 | ``` 29 | icon name 30 | ``` 31 | 32 | #### Using Open Iconic's SVG Sprite 33 | 34 | Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack. 35 | 36 | Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `` *tag and a unique class name for each different icon in the* `` *tag.* 37 | 38 | ``` 39 | 40 | 41 | 42 | ``` 43 | 44 | Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `` tag with equal width and height dimensions. 45 | 46 | ``` 47 | .icon { 48 | width: 16px; 49 | height: 16px; 50 | } 51 | ``` 52 | 53 | Coloring icons is even easier. All you need to do is set the `fill` rule on the `` tag. 54 | 55 | ``` 56 | .icon-account-login { 57 | fill: #f00; 58 | } 59 | ``` 60 | 61 | To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/). 62 | 63 | #### Using Open Iconic's Icon Font... 64 | 65 | 66 | ##### …with Bootstrap 67 | 68 | You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}` 69 | 70 | 71 | ``` 72 | 73 | ``` 74 | 75 | 76 | ``` 77 | 78 | ``` 79 | 80 | ##### …with Foundation 81 | 82 | You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}` 83 | 84 | ``` 85 | 86 | ``` 87 | 88 | 89 | ``` 90 | 91 | ``` 92 | 93 | ##### …on its own 94 | 95 | You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}` 96 | 97 | ``` 98 | 99 | ``` 100 | 101 | ``` 102 | 103 | ``` 104 | 105 | 106 | ## License 107 | 108 | ### Icons 109 | 110 | All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT). 111 | 112 | ### Fonts 113 | 114 | All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web). 115 | -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:Icons;src:url(../fonts/open-iconic.eot);src:url(../fonts/open-iconic.eot?#iconic-sm) format('embedded-opentype'),url(../fonts/open-iconic.woff) format('woff'),url(../fonts/open-iconic.ttf) format('truetype'),url(../fonts/open-iconic.otf) format('opentype'),url(../fonts/open-iconic.svg#iconic-sm) format('svg');font-weight:400;font-style:normal}.oi{position:relative;top:1px;display:inline-block;speak:none;font-family:Icons;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.oi:empty:before{width:1em;text-align:center;box-sizing:content-box}.oi.oi-align-center:before{text-align:center}.oi.oi-align-left:before{text-align:left}.oi.oi-align-right:before{text-align:right}.oi.oi-flip-horizontal:before{-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.oi.oi-flip-vertical:before{-webkit-transform:scale(1,-1);-ms-transform:scale(-1,1);transform:scale(1,-1)}.oi.oi-flip-horizontal-vertical:before{-webkit-transform:scale(-1,-1);-ms-transform:scale(-1,1);transform:scale(-1,-1)}.oi-account-login:before{content:'\e000'}.oi-account-logout:before{content:'\e001'}.oi-action-redo:before{content:'\e002'}.oi-action-undo:before{content:'\e003'}.oi-align-center:before{content:'\e004'}.oi-align-left:before{content:'\e005'}.oi-align-right:before{content:'\e006'}.oi-aperture:before{content:'\e007'}.oi-arrow-bottom:before{content:'\e008'}.oi-arrow-circle-bottom:before{content:'\e009'}.oi-arrow-circle-left:before{content:'\e00a'}.oi-arrow-circle-right:before{content:'\e00b'}.oi-arrow-circle-top:before{content:'\e00c'}.oi-arrow-left:before{content:'\e00d'}.oi-arrow-right:before{content:'\e00e'}.oi-arrow-thick-bottom:before{content:'\e00f'}.oi-arrow-thick-left:before{content:'\e010'}.oi-arrow-thick-right:before{content:'\e011'}.oi-arrow-thick-top:before{content:'\e012'}.oi-arrow-top:before{content:'\e013'}.oi-audio-spectrum:before{content:'\e014'}.oi-audio:before{content:'\e015'}.oi-badge:before{content:'\e016'}.oi-ban:before{content:'\e017'}.oi-bar-chart:before{content:'\e018'}.oi-basket:before{content:'\e019'}.oi-battery-empty:before{content:'\e01a'}.oi-battery-full:before{content:'\e01b'}.oi-beaker:before{content:'\e01c'}.oi-bell:before{content:'\e01d'}.oi-bluetooth:before{content:'\e01e'}.oi-bold:before{content:'\e01f'}.oi-bolt:before{content:'\e020'}.oi-book:before{content:'\e021'}.oi-bookmark:before{content:'\e022'}.oi-box:before{content:'\e023'}.oi-briefcase:before{content:'\e024'}.oi-british-pound:before{content:'\e025'}.oi-browser:before{content:'\e026'}.oi-brush:before{content:'\e027'}.oi-bug:before{content:'\e028'}.oi-bullhorn:before{content:'\e029'}.oi-calculator:before{content:'\e02a'}.oi-calendar:before{content:'\e02b'}.oi-camera-slr:before{content:'\e02c'}.oi-caret-bottom:before{content:'\e02d'}.oi-caret-left:before{content:'\e02e'}.oi-caret-right:before{content:'\e02f'}.oi-caret-top:before{content:'\e030'}.oi-cart:before{content:'\e031'}.oi-chat:before{content:'\e032'}.oi-check:before{content:'\e033'}.oi-chevron-bottom:before{content:'\e034'}.oi-chevron-left:before{content:'\e035'}.oi-chevron-right:before{content:'\e036'}.oi-chevron-top:before{content:'\e037'}.oi-circle-check:before{content:'\e038'}.oi-circle-x:before{content:'\e039'}.oi-clipboard:before{content:'\e03a'}.oi-clock:before{content:'\e03b'}.oi-cloud-download:before{content:'\e03c'}.oi-cloud-upload:before{content:'\e03d'}.oi-cloud:before{content:'\e03e'}.oi-cloudy:before{content:'\e03f'}.oi-code:before{content:'\e040'}.oi-cog:before{content:'\e041'}.oi-collapse-down:before{content:'\e042'}.oi-collapse-left:before{content:'\e043'}.oi-collapse-right:before{content:'\e044'}.oi-collapse-up:before{content:'\e045'}.oi-command:before{content:'\e046'}.oi-comment-square:before{content:'\e047'}.oi-compass:before{content:'\e048'}.oi-contrast:before{content:'\e049'}.oi-copywriting:before{content:'\e04a'}.oi-credit-card:before{content:'\e04b'}.oi-crop:before{content:'\e04c'}.oi-dashboard:before{content:'\e04d'}.oi-data-transfer-download:before{content:'\e04e'}.oi-data-transfer-upload:before{content:'\e04f'}.oi-delete:before{content:'\e050'}.oi-dial:before{content:'\e051'}.oi-document:before{content:'\e052'}.oi-dollar:before{content:'\e053'}.oi-double-quote-sans-left:before{content:'\e054'}.oi-double-quote-sans-right:before{content:'\e055'}.oi-double-quote-serif-left:before{content:'\e056'}.oi-double-quote-serif-right:before{content:'\e057'}.oi-droplet:before{content:'\e058'}.oi-eject:before{content:'\e059'}.oi-elevator:before{content:'\e05a'}.oi-ellipses:before{content:'\e05b'}.oi-envelope-closed:before{content:'\e05c'}.oi-envelope-open:before{content:'\e05d'}.oi-euro:before{content:'\e05e'}.oi-excerpt:before{content:'\e05f'}.oi-expand-down:before{content:'\e060'}.oi-expand-left:before{content:'\e061'}.oi-expand-right:before{content:'\e062'}.oi-expand-up:before{content:'\e063'}.oi-external-link:before{content:'\e064'}.oi-eye:before{content:'\e065'}.oi-eyedropper:before{content:'\e066'}.oi-file:before{content:'\e067'}.oi-fire:before{content:'\e068'}.oi-flag:before{content:'\e069'}.oi-flash:before{content:'\e06a'}.oi-folder:before{content:'\e06b'}.oi-fork:before{content:'\e06c'}.oi-fullscreen-enter:before{content:'\e06d'}.oi-fullscreen-exit:before{content:'\e06e'}.oi-globe:before{content:'\e06f'}.oi-graph:before{content:'\e070'}.oi-grid-four-up:before{content:'\e071'}.oi-grid-three-up:before{content:'\e072'}.oi-grid-two-up:before{content:'\e073'}.oi-hard-drive:before{content:'\e074'}.oi-header:before{content:'\e075'}.oi-headphones:before{content:'\e076'}.oi-heart:before{content:'\e077'}.oi-home:before{content:'\e078'}.oi-image:before{content:'\e079'}.oi-inbox:before{content:'\e07a'}.oi-infinity:before{content:'\e07b'}.oi-info:before{content:'\e07c'}.oi-italic:before{content:'\e07d'}.oi-justify-center:before{content:'\e07e'}.oi-justify-left:before{content:'\e07f'}.oi-justify-right:before{content:'\e080'}.oi-key:before{content:'\e081'}.oi-laptop:before{content:'\e082'}.oi-layers:before{content:'\e083'}.oi-lightbulb:before{content:'\e084'}.oi-link-broken:before{content:'\e085'}.oi-link-intact:before{content:'\e086'}.oi-list-rich:before{content:'\e087'}.oi-list:before{content:'\e088'}.oi-location:before{content:'\e089'}.oi-lock-locked:before{content:'\e08a'}.oi-lock-unlocked:before{content:'\e08b'}.oi-loop-circular:before{content:'\e08c'}.oi-loop-square:before{content:'\e08d'}.oi-loop:before{content:'\e08e'}.oi-magnifying-glass:before{content:'\e08f'}.oi-map-marker:before{content:'\e090'}.oi-map:before{content:'\e091'}.oi-media-pause:before{content:'\e092'}.oi-media-play:before{content:'\e093'}.oi-media-record:before{content:'\e094'}.oi-media-skip-backward:before{content:'\e095'}.oi-media-skip-forward:before{content:'\e096'}.oi-media-step-backward:before{content:'\e097'}.oi-media-step-forward:before{content:'\e098'}.oi-media-stop:before{content:'\e099'}.oi-medical-cross:before{content:'\e09a'}.oi-menu:before{content:'\e09b'}.oi-microphone:before{content:'\e09c'}.oi-minus:before{content:'\e09d'}.oi-monitor:before{content:'\e09e'}.oi-moon:before{content:'\e09f'}.oi-move:before{content:'\e0a0'}.oi-musical-note:before{content:'\e0a1'}.oi-paperclip:before{content:'\e0a2'}.oi-pencil:before{content:'\e0a3'}.oi-people:before{content:'\e0a4'}.oi-person:before{content:'\e0a5'}.oi-phone:before{content:'\e0a6'}.oi-pie-chart:before{content:'\e0a7'}.oi-pin:before{content:'\e0a8'}.oi-play-circle:before{content:'\e0a9'}.oi-plus:before{content:'\e0aa'}.oi-power-standby:before{content:'\e0ab'}.oi-print:before{content:'\e0ac'}.oi-project:before{content:'\e0ad'}.oi-pulse:before{content:'\e0ae'}.oi-puzzle-piece:before{content:'\e0af'}.oi-question-mark:before{content:'\e0b0'}.oi-rain:before{content:'\e0b1'}.oi-random:before{content:'\e0b2'}.oi-reload:before{content:'\e0b3'}.oi-resize-both:before{content:'\e0b4'}.oi-resize-height:before{content:'\e0b5'}.oi-resize-width:before{content:'\e0b6'}.oi-rss-alt:before{content:'\e0b7'}.oi-rss:before{content:'\e0b8'}.oi-script:before{content:'\e0b9'}.oi-share-boxed:before{content:'\e0ba'}.oi-share:before{content:'\e0bb'}.oi-shield:before{content:'\e0bc'}.oi-signal:before{content:'\e0bd'}.oi-signpost:before{content:'\e0be'}.oi-sort-ascending:before{content:'\e0bf'}.oi-sort-descending:before{content:'\e0c0'}.oi-spreadsheet:before{content:'\e0c1'}.oi-star:before{content:'\e0c2'}.oi-sun:before{content:'\e0c3'}.oi-tablet:before{content:'\e0c4'}.oi-tag:before{content:'\e0c5'}.oi-tags:before{content:'\e0c6'}.oi-target:before{content:'\e0c7'}.oi-task:before{content:'\e0c8'}.oi-terminal:before{content:'\e0c9'}.oi-text:before{content:'\e0ca'}.oi-thumb-down:before{content:'\e0cb'}.oi-thumb-up:before{content:'\e0cc'}.oi-timer:before{content:'\e0cd'}.oi-transfer:before{content:'\e0ce'}.oi-trash:before{content:'\e0cf'}.oi-underline:before{content:'\e0d0'}.oi-vertical-align-bottom:before{content:'\e0d1'}.oi-vertical-align-center:before{content:'\e0d2'}.oi-vertical-align-top:before{content:'\e0d3'}.oi-video:before{content:'\e0d4'}.oi-volume-high:before{content:'\e0d5'}.oi-volume-low:before{content:'\e0d6'}.oi-volume-off:before{content:'\e0d7'}.oi-warning:before{content:'\e0d8'}.oi-wifi:before{content:'\e0d9'}.oi-wrench:before{content:'\e0da'}.oi-x:before{content:'\e0db'}.oi-yen:before{content:'\e0dc'}.oi-zoom-in:before{content:'\e0dd'}.oi-zoom-out:before{content:'\e0de'} -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/samples/BlazorSample/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/samples/BlazorSample/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/samples/BlazorSample/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/samples/BlazorSample/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | @import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); 2 | 3 | html, body { 4 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 5 | } 6 | 7 | app { 8 | position: relative; 9 | display: flex; 10 | flex-direction: column; 11 | } 12 | 13 | .top-row { 14 | height: 3.5rem; 15 | display: flex; 16 | align-items: center; 17 | } 18 | 19 | .main { 20 | flex: 1; 21 | } 22 | 23 | .main .top-row { 24 | background-color: #e6e6e6; 25 | border-bottom: 1px solid #d6d5d5; 26 | } 27 | 28 | .sidebar { 29 | background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); 30 | } 31 | 32 | .sidebar .top-row { 33 | background-color: rgba(0,0,0,0.4); 34 | } 35 | 36 | .sidebar .navbar-brand { 37 | font-size: 1.1rem; 38 | } 39 | 40 | .sidebar .oi { 41 | width: 2rem; 42 | font-size: 1.1rem; 43 | vertical-align: text-top; 44 | top: -2px; 45 | } 46 | 47 | .nav-item { 48 | font-size: 0.9rem; 49 | padding-bottom: 0.5rem; 50 | } 51 | 52 | .nav-item:first-of-type { 53 | padding-top: 1rem; 54 | } 55 | 56 | .nav-item:last-of-type { 57 | padding-bottom: 1rem; 58 | } 59 | 60 | .nav-item a { 61 | color: #d7d7d7; 62 | border-radius: 4px; 63 | height: 3rem; 64 | display: flex; 65 | align-items: center; 66 | line-height: 3rem; 67 | } 68 | 69 | .nav-item a.active { 70 | background-color: rgba(255,255,255,0.25); 71 | color: white; 72 | } 73 | 74 | .nav-item a:hover { 75 | background-color: rgba(255,255,255,0.1); 76 | color: white; 77 | } 78 | 79 | .content { 80 | padding-top: 1.1rem; 81 | } 82 | 83 | .navbar-toggler { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | } 86 | 87 | @media (max-width: 767.98px) { 88 | .main .top-row { 89 | display: none; 90 | } 91 | } 92 | 93 | @media (min-width: 768px) { 94 | app { 95 | flex-direction: row; 96 | } 97 | 98 | .sidebar { 99 | width: 250px; 100 | height: 100vh; 101 | position: sticky; 102 | top: 0; 103 | } 104 | 105 | .main .top-row { 106 | position: sticky; 107 | top: 0; 108 | } 109 | 110 | .main > div { 111 | padding-left: 2rem !important; 112 | padding-right: 1.5rem !important; 113 | } 114 | 115 | .navbar-toggler { 116 | display: none; 117 | } 118 | 119 | .sidebar .collapse { 120 | /* Never collapse the sidebar for wide screens */ 121 | display: block; 122 | } 123 | } 124 | 125 | .liquid-custom-modal { 126 | display: flex; 127 | flex-direction: column; 128 | width: 60vw; 129 | height: 60vh; 130 | background-color: #fafafa; 131 | border-radius: 12px; 132 | border: 1px solid #fff; 133 | padding: 0.5rem; 134 | z-index: 102; 135 | box-shadow: 0 2px 2px rgba(0,0,0,.75); 136 | } 137 | 138 | .liquid-prompt-modal { 139 | display: flex; 140 | flex-direction: column; 141 | width: 600px; 142 | background-color: #fefefe; 143 | border-radius: 4px; 144 | border: 1px solid #fff; 145 | padding: 0.5rem; 146 | z-index: 102; 147 | box-shadow: 0 3px 3px rgba(0,0,0,.75); 148 | } 149 | 150 | .liquid-prompt-modal .liquid-modal-dialog-header { 151 | display: none; 152 | } -------------------------------------------------------------------------------- /samples/BlazorSample/wwwroot/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Liquid Technologies Modal Dialog 7 | 8 | 9 | 10 | 11 | 12 | Loading... 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 |

Sorry, there's nothing at this address.

9 |
10 |
11 |
12 |
-------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/BackGroundCancel.razor: -------------------------------------------------------------------------------- 1 | @page "/backgroundcancel" 2 | @inject IModalDialogService ModalDialog 3 | 4 |

Click background to cancel

5 | 6 |
7 | 8 |

9 | A modal is cancelled by default if the user clicks outside the modal. This behavior can 10 | be disabled. 11 |

12 | 13 | 14 | 15 | @code { 16 | 17 | void BackgroundCancelEnabled() 18 | { 19 | var parameters = new ModalDialogParameters(); 20 | parameters.Add("FormId", 11); 21 | var options = new ModalDialogOptions() { BackgroundClickToClose = true }; 22 | 23 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 24 | } 25 | 26 | void BackgroundCancelDisabled() 27 | { 28 | var parameters = new ModalDialogParameters(); 29 | parameters.Add("FormId", 11); 30 | var options = new ModalDialogOptions() { BackgroundClickToClose = false }; 31 | 32 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/CustomStyle.razor: -------------------------------------------------------------------------------- 1 | @page "/custom" 2 | @inject IModalDialogService ModalDialog 3 | @layout CustomModalLayout 4 | 5 |

Liquid Technologies Modal Dialog Sample with Custom Styling

6 | 7 |
8 |

9 | A custom style can also be set as a parameter on the Modal.Show() method. 10 |

11 | 12 | 13 |
14 |

15 | The same dialog with the default styling: 16 |

17 | 18 | 19 | 20 | @code { 21 | 22 | void ShowModalCustomStyle() 23 | { 24 | var options = new ModalDialogOptions() { Style = "liquid-prompt-modal" }; 25 | 26 | ModalDialog.ShowDialogAsync("Delete record?", options); 27 | } 28 | 29 | void ShowModal() 30 | { 31 | ModalDialog.ShowDialogAsync("Delete record?"); 32 | } 33 | } -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/DataInputFormDemo.razor: -------------------------------------------------------------------------------- 1 | @page "/datainputformdemo" 2 | @inject IModalDialogService ModalService 3 | 4 |

Liquid Technologies Modal Dialog Sample

5 | 6 |
7 | 8 |

9 | This example also show how to quickly create data entry forms. 10 |

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
Name@Name
Gender@Gender
Age@Age
Married@Married
32 | 33 | 34 | 35 | 36 |
37 | 38 |

Sample Code

39 |
 40 | @@inject IModalDialogService ModalService
 41 | 
 42 | ...
 43 | 
 44 | @@code 
 45 | {
 46 |     enum GenderType { Male, Female }
 47 | 
 48 |     private string Name = "Fred";
 49 |     private GenderType Gender = GenderType.Male;
 50 |     private int Age = 25;
 51 |     private bool Married = false;
 52 | 
 53 | 
 54 |     async void Edit_Clicked()
 55 |     {
 56 |         ModalDataInputForm frm = new ModalDataInputForm("Edit Data", "A description of the data");
 57 | 
 58 |         var nameFld = frm.AddStringField("Name", "First Name", this.Name, "the users first name");
 59 |         var genderFld = frm.AddEnumField<GenderType>("Gender", "Sex", this.Gender, "the users gender");
 60 |         var ageFld = frm.AddIntField("Age", "Age", this.Age, "the age of the user", min:0, max:130);
 61 |         var marriedFld = frm.AddBoolField("Married", "Is Married", this.Married, "is the user married");
 62 | 
 63 |         if (await frm.ShowAsync(ModalService))
 64 |         {
 65 |             this.Name = nameFld.Value;
 66 |             this.Gender = genderFld.Value;
 67 |             this.Age = ageFld.Value;
 68 |             this.Married = marriedFld.Value;
 69 |             StateHasChanged();
 70 |         }
 71 |     }
 72 | }
 73 | 
74 | 75 | @code { 76 | 77 | enum GenderType { Male, Female } 78 | 79 | private string Name = "Fred"; 80 | private GenderType Gender = GenderType.Male; 81 | private int Age = 25; 82 | private bool Married = false; 83 | 84 | 85 | async void Edit_Clicked() 86 | { 87 | ModalDataInputForm frm = new ModalDataInputForm("Edit Data", "A description of the data"); 88 | 89 | var nameFld = frm.AddStringField("Name", "First Name", this.Name, "the users first name"); 90 | var genderFld = frm.AddEnumField("Gender", "Sex", this.Gender, "the users gender"); 91 | var ageFld = frm.AddIntField("Age", "Age", this.Age, "the age of the user", min: 0, max: 130); 92 | var marriedFld = frm.AddBoolField("Married", "Is Married", this.Married, "is the user married"); 93 | 94 | if (await frm.ShowAsync(ModalService)) 95 | { 96 | this.Name = nameFld.Value; 97 | this.Gender = genderFld.Value; 98 | this.Age = ageFld.Value; 99 | this.Married = marriedFld.Value; 100 | StateHasChanged(); 101 | } 102 | } 103 | } 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/HideCloseButton.razor: -------------------------------------------------------------------------------- 1 | @page "/closebutton" 2 | @inject IModalDialogService ModalDialog 3 | 4 |

Hiding the modal close button

5 | 6 |
7 | 8 |

9 | Liquid Technologies Modal Dialog shows a close button in the modal by default. The button can be hidden if you 10 | prefer to handle closing the modal yourself. 11 |

12 | 13 | 14 | 15 | 16 | @code { 17 | 18 | void CloseButtonShown() 19 | { 20 | var parameters = new ModalDialogParameters(); 21 | parameters.Add("FormId", 11); 22 | 23 | var options = new ModalDialogOptions() { ShowCloseButton = true }; 24 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 25 | } 26 | 27 | void CloseButtonHidden() 28 | { 29 | var parameters = new ModalDialogParameters(); 30 | parameters.Add("FormId", 11); 31 | 32 | var options = new ModalDialogOptions() { ShowCloseButton = false }; 33 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @inject IModalDialogService ModalDialog 3 | 4 |

Liquid Technologies Modal Dialog Sample

5 | 6 |
7 | 8 |

9 | This example shows how a ModalDialog can be incorporated into the 10 | logical flow of an async function, and how data can be passed to 11 | and retrieved. 12 |

13 | 14 |
15 | 
16 |     async void ShowModal()
17 |     {
18 |         // Arguments can be passed into the modal dialog
19 |         var parameters = new ModalDialogParameters();
20 |         parameters.Add("FormId", 11);
21 | 
22 |         // using await will cause execution to resume when the dialog has been closed.
23 |         ModalDialogResult result = await ModalDialog.ShowDialogAsync<SignUpForm>("Sign Up Form", null, parameters);
24 |         if (result.Success)
25 |             Message = "User Provided the value : " + result.ReturnParameters.Get<string>("FullName");
26 |         else
27 |             Message = "User Cancelled";
28 |     }
29 | 
30 | 31 |

32 | This example also show the ability to nest dialog boxes, for examples 33 | if you submit the popup form without populating any data, a confirmation 34 | dialog is shown over the top of the active dialog. 35 |

36 | 37 | 38 | 39 |

@Message

40 | 41 | @code { 42 | string Message = ""; 43 | 44 | 45 | async void ShowModal() 46 | { 47 | Message = "Requesting Data From User"; 48 | StateHasChanged(); 49 | 50 | var parameters = new ModalDialogParameters(); 51 | parameters.Add("FormId", 11); 52 | ModalDialogResult result = await ModalDialog.ShowDialogAsync("Sign Up Form", null, parameters); 53 | if (result.Success) 54 | Message = "User Provided the value : " + result.ReturnParameters.Get("FullName"); 55 | else 56 | Message = "User Cancelled"; 57 | StateHasChanged(); 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/MessageBox.razor: -------------------------------------------------------------------------------- 1 | @page "/messagebox" 2 | @inject IModalDialogService ModalDialog 3 | @layout CustomModalLayout 4 | 5 |

Liquid Technologies Modal Dialog Sample MessageBox's

6 | 7 |
8 | 9 |

10 | Shows how basic MessageBoxes can be displayed: 11 |

12 |

13 | 14 |

15 |

16 | 17 |

18 |

19 | 20 |

21 |

22 | 23 |

24 | 25 |
26 | Last Message box result : @LastMessageBoxResult 27 |
28 | 29 | @code { 30 | 31 | string LastMessageBoxResult = "Not Set"; 32 | 33 | async void ShowMessageBoxOK() 34 | { 35 | MessageBoxDialogResult result = await ModalDialog.ShowMessageBoxAsync("Simple Message Box", "Click OK, the close button or the background to Close", MessageBoxButtons.OK, MessageBoxDefaultButton.Button1); 36 | 37 | LastMessageBoxResult = result.ToString(); 38 | StateHasChanged(); 39 | } 40 | 41 | async void ShowMessageBoxYesNoCancel() 42 | { 43 | MessageBoxDialogResult result = await ModalDialog.ShowMessageBoxAsync("Yes/No/Cancel Message Box", "Clicking the close button or the background is equivient to the Cancel button. Setting the default button to Button2 causes the 'No' button to be highlighted.", MessageBoxButtons.YesNoCancel, MessageBoxDefaultButton.Button2); 44 | LastMessageBoxResult = result.ToString(); 45 | StateHasChanged(); 46 | } 47 | 48 | async void ShowMessageBoxYesNo() 49 | { 50 | MessageBoxDialogResult result = await ModalDialog.ShowMessageBoxAsync("Yes/No Message Box", "Requires the Yes/No button to be pressed, can't be dismissed with the close or clicking in the background", MessageBoxButtons.YesNo, MessageBoxDefaultButton.Button2); 51 | LastMessageBoxResult = result.ToString(); 52 | StateHasChanged(); 53 | } 54 | 55 | async void ShowMessageBoxAbortRetryIgnore() 56 | { 57 | MessageBoxDialogResult result = await ModalDialog.ShowMessageBoxAsync("Abort/Retry/Ignore Message Box", "Requires the Abort/Retry/Ignore button to be pressed, can't be dismissed with the close or clicking in the background", MessageBoxButtons.AbortRetryIgnore, MessageBoxDefaultButton.Button3); 58 | LastMessageBoxResult = result.ToString(); 59 | StateHasChanged(); 60 | } 61 | 62 | } 63 | 64 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/Position.razor: -------------------------------------------------------------------------------- 1 | @page "/position" 2 | @inject IModalDialogService ModalDialog 3 | 4 |

Positioning the modal

5 | 6 |
7 | 8 |

9 | The modal is shown in the center of the viewport by default. The modal can be shown 10 | in different positions if needed. The positioning is flexible as it is set using 11 | CSS styling. 12 |

13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | @code { 21 | 22 | void PositionCenter() 23 | { 24 | var parameters = new ModalDialogParameters(); 25 | parameters.Add("FormId", 11); 26 | 27 | ModalDialog.ShowDialogAsync("Sign Up Form", null, parameters); 28 | } 29 | 30 | void PositionCustom(string position) 31 | { 32 | var parameters = new ModalDialogParameters(); 33 | parameters.Add("FormId", 11); 34 | var options = new ModalDialogOptions() { Position = position }; 35 | 36 | ModalDialog.ShowDialogAsync("Sign Up Form", options, parameters); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/ScrollableForm.razor: -------------------------------------------------------------------------------- 1 | @page "/scrollableform" 2 | @inject IModalDialogService ModalService 3 | 4 |

Liquid Technologies Modal Dialog Sample

5 | 6 |
7 | 8 |

9 | This example also show how the form displays the form when it contains to much information for the screen. 10 |

11 | 12 | 13 | 14 |
15 | 16 |

Sample Code

17 |
18 | @@inject IModalDialogService ModalService
19 | 
20 | ...
21 | 
22 | @@code {
23 | 
24 |     async void Edit_Clicked()
25 |     {
26 |         ModalDataInputForm frm = new ModalDataInputForm("Edit Data", "When the fields are to big to fit on the form");
27 | 
28 |         for(int i=0;i<30;i++)
29 |             frm.AddStringField($"Field{i}", $"Field {i}", $"Value {i}", $"Field {i}");
30 | 
31 |         await frm.ShowAsync(ModalService);
32 |     }
33 | }
34 | 
35 | 36 | @code { 37 | 38 | async void Edit_Clicked() 39 | { 40 | ModalDataInputForm frm = new ModalDataInputForm("Edit Data", "When the fields are to big to fit on the form"); 41 | 42 | for(int i=0;i<30;i++) 43 | frm.AddStringField($"Field{i}", $"Field {i}", $"Value {i}", $"Field {i}"); 44 | 45 | await frm.ShowAsync(ModalService); 46 | } 47 | } 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/SignUpForm.razor: -------------------------------------------------------------------------------- 1 | @inject IModalDialogService ModalDialogService 2 | 3 |

Form Id input Parameter : @FormId

4 | 5 |
6 | 7 |
8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 | 19 |
20 | 21 | 22 | @code { 23 | 24 | [Parameter] 25 | public string FirstName { get; set; } 26 | [Parameter] 27 | public string LastName { get; set; } 28 | [Parameter] 29 | public int FormId { get; set; } 30 | 31 | async void Ok_Clicked() 32 | { 33 | try 34 | { 35 | if (string.IsNullOrWhiteSpace(FirstName) && string.IsNullOrWhiteSpace(LastName)) 36 | { 37 | ModalDialogResult result = await ModalDialogService.ShowDialogAsync("Validation Errors"); 38 | if (result.Success == false) 39 | ModalDialogService.Close(false); 40 | } 41 | else 42 | { 43 | ModalDialogParameters resultParameters = new ModalDialogParameters(); 44 | resultParameters.Set("FirstName", FirstName); 45 | resultParameters.Set("LastName", LastName); 46 | resultParameters.Set("FullName", FirstName + " " + LastName); 47 | ModalDialogService.Close(true, resultParameters); 48 | } 49 | } 50 | catch (Exception ex) 51 | { 52 | // pass the exception back to the ShowDialogAsync call that opened the Dialog 53 | ModalDialogService.Close(ex); 54 | } 55 | } 56 | 57 | void Cancel_Clicked() 58 | { 59 | ModalDialogService.Close(false); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/ValidationErrorForm.razor: -------------------------------------------------------------------------------- 1 | @inject IModalDialogService ModalDialogService 2 | 3 |
4 |
5 |

The data you have entered is incomplete or contains errors.

6 |

This demonstrates using nested dialogs, i.e. the Errors dialog over the SignUp form

7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | @code { 15 | 16 | void Retry_Clicked() 17 | { 18 | ModalDialogService.Close(true); 19 | } 20 | 21 | void Cancel_Clicked() 22 | { 23 | ModalDialogService.Close(false); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace ServerSideblazor.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | 5 | 6 | 7 | 8 | 9 | 10 | ServerSideblazor 11 | 12 | 13 | 14 | 15 | 16 | 17 | @(await Html.RenderComponentAsync(RenderMode.Server)) 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Pages/_Imports.razor: -------------------------------------------------------------------------------- 1 | @layout MainLayout 2 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.Extensions.Logging; 11 | 12 | namespace ServerSideblazor 13 | { 14 | public class Program 15 | { 16 | public static void Main(string[] args) 17 | { 18 | CreateHostBuilder(args).Build().Run(); 19 | } 20 | 21 | public static IHostBuilder CreateHostBuilder(string[] args) => 22 | Host.CreateDefaultBuilder(args) 23 | .ConfigureWebHostDefaults(webBuilder => 24 | { 25 | webBuilder.UseStartup(); 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/ServerSideblazor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | 7.3 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Shared/CustomModalLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 4 | 5 | 8 | 9 |
10 |
11 | About 12 |
13 | 14 |
15 | @Body 16 |
17 |
18 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 4 | 5 | 8 | 9 |
10 |
11 | About 12 |
13 | 14 |
15 | @Body 16 |
17 |
18 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  7 | 8 |
9 | 37 |
38 | 39 | @code { 40 | bool collapseNavMenu = true; 41 | 42 | string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 43 | 44 | void ToggleNavMenu() 45 | { 46 | collapseNavMenu = !collapseNavMenu; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/Startup.cs: -------------------------------------------------------------------------------- 1 | using Blazor.ModalDialog; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Hosting; 7 | 8 | namespace ServerSideblazor 9 | { 10 | public class Startup 11 | { 12 | public Startup(IConfiguration configuration) 13 | { 14 | Configuration = configuration; 15 | } 16 | 17 | public IConfiguration Configuration { get; } 18 | 19 | // This method gets called by the runtime. Use this method to add services to the container. 20 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 21 | public void ConfigureServices(IServiceCollection services) 22 | { 23 | services.AddRazorPages(); 24 | services.AddServerSideBlazor(); 25 | services.AddModalDialog(); 26 | } 27 | 28 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 29 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 30 | { 31 | if (env.IsDevelopment()) 32 | { 33 | app.UseDeveloperExceptionPage(); 34 | } 35 | else 36 | { 37 | app.UseExceptionHandler("/Home/Error"); 38 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 39 | app.UseHsts(); 40 | } 41 | 42 | app.UseHttpsRedirection(); 43 | app.UseStaticFiles(); 44 | 45 | app.UseRouting(); 46 | 47 | app.UseEndpoints(endpoints => 48 | { 49 | endpoints.MapBlazorHub(); 50 | endpoints.MapFallbackToPage("/_Host"); 51 | }); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Authorization 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using ServerSideblazor 9 | @using ServerSideblazor.Shared 10 | 11 | @using Blazor.ModalDialog 12 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/css/open-iconic/FONT-LICENSE: -------------------------------------------------------------------------------- 1 | SIL OPEN FONT LICENSE Version 1.1 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | PREAMBLE 6 | The goals of the Open Font License (OFL) are to stimulate worldwide 7 | development of collaborative font projects, to support the font creation 8 | efforts of academic and linguistic communities, and to provide a free and 9 | open framework in which fonts may be shared and improved in partnership 10 | with others. 11 | 12 | The OFL allows the licensed fonts to be used, studied, modified and 13 | redistributed freely as long as they are not sold by themselves. The 14 | fonts, including any derivative works, can be bundled, embedded, 15 | redistributed and/or sold with any software provided that any reserved 16 | names are not used by derivative works. The fonts and derivatives, 17 | however, cannot be released under any other type of license. The 18 | requirement for fonts to remain under this license does not apply 19 | to any document created using the fonts or their derivatives. 20 | 21 | DEFINITIONS 22 | "Font Software" refers to the set of files released by the Copyright 23 | Holder(s) under this license and clearly marked as such. This may 24 | include source files, build scripts and documentation. 25 | 26 | "Reserved Font Name" refers to any names specified as such after the 27 | copyright statement(s). 28 | 29 | "Original Version" refers to the collection of Font Software components as 30 | distributed by the Copyright Holder(s). 31 | 32 | "Modified Version" refers to any derivative made by adding to, deleting, 33 | or substituting -- in part or in whole -- any of the components of the 34 | Original Version, by changing formats or by porting the Font Software to a 35 | new environment. 36 | 37 | "Author" refers to any designer, engineer, programmer, technical 38 | writer or other person who contributed to the Font Software. 39 | 40 | PERMISSION & CONDITIONS 41 | Permission is hereby granted, free of charge, to any person obtaining 42 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 43 | redistribute, and sell modified and unmodified copies of the Font 44 | Software, subject to the following conditions: 45 | 46 | 1) Neither the Font Software nor any of its individual components, 47 | in Original or Modified Versions, may be sold by itself. 48 | 49 | 2) Original or Modified Versions of the Font Software may be bundled, 50 | redistributed and/or sold with any software, provided that each copy 51 | contains the above copyright notice and this license. These can be 52 | included either as stand-alone text files, human-readable headers or 53 | in the appropriate machine-readable metadata fields within text or 54 | binary files as long as those fields can be easily viewed by the user. 55 | 56 | 3) No Modified Version of the Font Software may use the Reserved Font 57 | Name(s) unless explicit written permission is granted by the corresponding 58 | Copyright Holder. This restriction only applies to the primary font name as 59 | presented to the users. 60 | 61 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 62 | Software shall not be used to promote, endorse or advertise any 63 | Modified Version, except to acknowledge the contribution(s) of the 64 | Copyright Holder(s) and the Author(s) or with their explicit written 65 | permission. 66 | 67 | 5) The Font Software, modified or unmodified, in part or in whole, 68 | must be distributed entirely under this license, and must not be 69 | distributed under any other license. The requirement for fonts to 70 | remain under this license does not apply to any document created 71 | using the Font Software. 72 | 73 | TERMINATION 74 | This license becomes null and void if any of the above conditions are 75 | not met. 76 | 77 | DISCLAIMER 78 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 79 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 80 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 81 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 82 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 83 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 84 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 85 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 86 | OTHER DEALINGS IN THE FONT SOFTWARE. 87 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/css/open-iconic/README.md: -------------------------------------------------------------------------------- 1 | [Open Iconic v1.1.1](http://useiconic.com/open) 2 | =========== 3 | 4 | ### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons) 5 | 6 | 7 | 8 | ## What's in Open Iconic? 9 | 10 | * 223 icons designed to be legible down to 8 pixels 11 | * Super-light SVG files - 61.8 for the entire set 12 | * SVG sprite—the modern replacement for icon fonts 13 | * Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats 14 | * Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats 15 | * PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px. 16 | 17 | 18 | ## Getting Started 19 | 20 | #### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections. 21 | 22 | ### General Usage 23 | 24 | #### Using Open Iconic's SVGs 25 | 26 | We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute). 27 | 28 | ``` 29 | icon name 30 | ``` 31 | 32 | #### Using Open Iconic's SVG Sprite 33 | 34 | Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack. 35 | 36 | Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `` *tag and a unique class name for each different icon in the* `` *tag.* 37 | 38 | ``` 39 | 40 | 41 | 42 | ``` 43 | 44 | Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `` tag with equal width and height dimensions. 45 | 46 | ``` 47 | .icon { 48 | width: 16px; 49 | height: 16px; 50 | } 51 | ``` 52 | 53 | Coloring icons is even easier. All you need to do is set the `fill` rule on the `` tag. 54 | 55 | ``` 56 | .icon-account-login { 57 | fill: #f00; 58 | } 59 | ``` 60 | 61 | To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/). 62 | 63 | #### Using Open Iconic's Icon Font... 64 | 65 | 66 | ##### …with Bootstrap 67 | 68 | You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}` 69 | 70 | 71 | ``` 72 | 73 | ``` 74 | 75 | 76 | ``` 77 | 78 | ``` 79 | 80 | ##### …with Foundation 81 | 82 | You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}` 83 | 84 | ``` 85 | 86 | ``` 87 | 88 | 89 | ``` 90 | 91 | ``` 92 | 93 | ##### …on its own 94 | 95 | You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}` 96 | 97 | ``` 98 | 99 | ``` 100 | 101 | ``` 102 | 103 | ``` 104 | 105 | 106 | ## License 107 | 108 | ### Icons 109 | 110 | All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT). 111 | 112 | ### Fonts 113 | 114 | All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web). 115 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:Icons;src:url(../fonts/open-iconic.eot);src:url(../fonts/open-iconic.eot?#iconic-sm) format('embedded-opentype'),url(../fonts/open-iconic.woff) format('woff'),url(../fonts/open-iconic.ttf) format('truetype'),url(../fonts/open-iconic.otf) format('opentype'),url(../fonts/open-iconic.svg#iconic-sm) format('svg');font-weight:400;font-style:normal}.oi{position:relative;top:1px;display:inline-block;speak:none;font-family:Icons;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.oi:empty:before{width:1em;text-align:center;box-sizing:content-box}.oi.oi-align-center:before{text-align:center}.oi.oi-align-left:before{text-align:left}.oi.oi-align-right:before{text-align:right}.oi.oi-flip-horizontal:before{-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.oi.oi-flip-vertical:before{-webkit-transform:scale(1,-1);-ms-transform:scale(-1,1);transform:scale(1,-1)}.oi.oi-flip-horizontal-vertical:before{-webkit-transform:scale(-1,-1);-ms-transform:scale(-1,1);transform:scale(-1,-1)}.oi-account-login:before{content:'\e000'}.oi-account-logout:before{content:'\e001'}.oi-action-redo:before{content:'\e002'}.oi-action-undo:before{content:'\e003'}.oi-align-center:before{content:'\e004'}.oi-align-left:before{content:'\e005'}.oi-align-right:before{content:'\e006'}.oi-aperture:before{content:'\e007'}.oi-arrow-bottom:before{content:'\e008'}.oi-arrow-circle-bottom:before{content:'\e009'}.oi-arrow-circle-left:before{content:'\e00a'}.oi-arrow-circle-right:before{content:'\e00b'}.oi-arrow-circle-top:before{content:'\e00c'}.oi-arrow-left:before{content:'\e00d'}.oi-arrow-right:before{content:'\e00e'}.oi-arrow-thick-bottom:before{content:'\e00f'}.oi-arrow-thick-left:before{content:'\e010'}.oi-arrow-thick-right:before{content:'\e011'}.oi-arrow-thick-top:before{content:'\e012'}.oi-arrow-top:before{content:'\e013'}.oi-audio-spectrum:before{content:'\e014'}.oi-audio:before{content:'\e015'}.oi-badge:before{content:'\e016'}.oi-ban:before{content:'\e017'}.oi-bar-chart:before{content:'\e018'}.oi-basket:before{content:'\e019'}.oi-battery-empty:before{content:'\e01a'}.oi-battery-full:before{content:'\e01b'}.oi-beaker:before{content:'\e01c'}.oi-bell:before{content:'\e01d'}.oi-bluetooth:before{content:'\e01e'}.oi-bold:before{content:'\e01f'}.oi-bolt:before{content:'\e020'}.oi-book:before{content:'\e021'}.oi-bookmark:before{content:'\e022'}.oi-box:before{content:'\e023'}.oi-briefcase:before{content:'\e024'}.oi-british-pound:before{content:'\e025'}.oi-browser:before{content:'\e026'}.oi-brush:before{content:'\e027'}.oi-bug:before{content:'\e028'}.oi-bullhorn:before{content:'\e029'}.oi-calculator:before{content:'\e02a'}.oi-calendar:before{content:'\e02b'}.oi-camera-slr:before{content:'\e02c'}.oi-caret-bottom:before{content:'\e02d'}.oi-caret-left:before{content:'\e02e'}.oi-caret-right:before{content:'\e02f'}.oi-caret-top:before{content:'\e030'}.oi-cart:before{content:'\e031'}.oi-chat:before{content:'\e032'}.oi-check:before{content:'\e033'}.oi-chevron-bottom:before{content:'\e034'}.oi-chevron-left:before{content:'\e035'}.oi-chevron-right:before{content:'\e036'}.oi-chevron-top:before{content:'\e037'}.oi-circle-check:before{content:'\e038'}.oi-circle-x:before{content:'\e039'}.oi-clipboard:before{content:'\e03a'}.oi-clock:before{content:'\e03b'}.oi-cloud-download:before{content:'\e03c'}.oi-cloud-upload:before{content:'\e03d'}.oi-cloud:before{content:'\e03e'}.oi-cloudy:before{content:'\e03f'}.oi-code:before{content:'\e040'}.oi-cog:before{content:'\e041'}.oi-collapse-down:before{content:'\e042'}.oi-collapse-left:before{content:'\e043'}.oi-collapse-right:before{content:'\e044'}.oi-collapse-up:before{content:'\e045'}.oi-command:before{content:'\e046'}.oi-comment-square:before{content:'\e047'}.oi-compass:before{content:'\e048'}.oi-contrast:before{content:'\e049'}.oi-copywriting:before{content:'\e04a'}.oi-credit-card:before{content:'\e04b'}.oi-crop:before{content:'\e04c'}.oi-dashboard:before{content:'\e04d'}.oi-data-transfer-download:before{content:'\e04e'}.oi-data-transfer-upload:before{content:'\e04f'}.oi-delete:before{content:'\e050'}.oi-dial:before{content:'\e051'}.oi-document:before{content:'\e052'}.oi-dollar:before{content:'\e053'}.oi-double-quote-sans-left:before{content:'\e054'}.oi-double-quote-sans-right:before{content:'\e055'}.oi-double-quote-serif-left:before{content:'\e056'}.oi-double-quote-serif-right:before{content:'\e057'}.oi-droplet:before{content:'\e058'}.oi-eject:before{content:'\e059'}.oi-elevator:before{content:'\e05a'}.oi-ellipses:before{content:'\e05b'}.oi-envelope-closed:before{content:'\e05c'}.oi-envelope-open:before{content:'\e05d'}.oi-euro:before{content:'\e05e'}.oi-excerpt:before{content:'\e05f'}.oi-expand-down:before{content:'\e060'}.oi-expand-left:before{content:'\e061'}.oi-expand-right:before{content:'\e062'}.oi-expand-up:before{content:'\e063'}.oi-external-link:before{content:'\e064'}.oi-eye:before{content:'\e065'}.oi-eyedropper:before{content:'\e066'}.oi-file:before{content:'\e067'}.oi-fire:before{content:'\e068'}.oi-flag:before{content:'\e069'}.oi-flash:before{content:'\e06a'}.oi-folder:before{content:'\e06b'}.oi-fork:before{content:'\e06c'}.oi-fullscreen-enter:before{content:'\e06d'}.oi-fullscreen-exit:before{content:'\e06e'}.oi-globe:before{content:'\e06f'}.oi-graph:before{content:'\e070'}.oi-grid-four-up:before{content:'\e071'}.oi-grid-three-up:before{content:'\e072'}.oi-grid-two-up:before{content:'\e073'}.oi-hard-drive:before{content:'\e074'}.oi-header:before{content:'\e075'}.oi-headphones:before{content:'\e076'}.oi-heart:before{content:'\e077'}.oi-home:before{content:'\e078'}.oi-image:before{content:'\e079'}.oi-inbox:before{content:'\e07a'}.oi-infinity:before{content:'\e07b'}.oi-info:before{content:'\e07c'}.oi-italic:before{content:'\e07d'}.oi-justify-center:before{content:'\e07e'}.oi-justify-left:before{content:'\e07f'}.oi-justify-right:before{content:'\e080'}.oi-key:before{content:'\e081'}.oi-laptop:before{content:'\e082'}.oi-layers:before{content:'\e083'}.oi-lightbulb:before{content:'\e084'}.oi-link-broken:before{content:'\e085'}.oi-link-intact:before{content:'\e086'}.oi-list-rich:before{content:'\e087'}.oi-list:before{content:'\e088'}.oi-location:before{content:'\e089'}.oi-lock-locked:before{content:'\e08a'}.oi-lock-unlocked:before{content:'\e08b'}.oi-loop-circular:before{content:'\e08c'}.oi-loop-square:before{content:'\e08d'}.oi-loop:before{content:'\e08e'}.oi-magnifying-glass:before{content:'\e08f'}.oi-map-marker:before{content:'\e090'}.oi-map:before{content:'\e091'}.oi-media-pause:before{content:'\e092'}.oi-media-play:before{content:'\e093'}.oi-media-record:before{content:'\e094'}.oi-media-skip-backward:before{content:'\e095'}.oi-media-skip-forward:before{content:'\e096'}.oi-media-step-backward:before{content:'\e097'}.oi-media-step-forward:before{content:'\e098'}.oi-media-stop:before{content:'\e099'}.oi-medical-cross:before{content:'\e09a'}.oi-menu:before{content:'\e09b'}.oi-microphone:before{content:'\e09c'}.oi-minus:before{content:'\e09d'}.oi-monitor:before{content:'\e09e'}.oi-moon:before{content:'\e09f'}.oi-move:before{content:'\e0a0'}.oi-musical-note:before{content:'\e0a1'}.oi-paperclip:before{content:'\e0a2'}.oi-pencil:before{content:'\e0a3'}.oi-people:before{content:'\e0a4'}.oi-person:before{content:'\e0a5'}.oi-phone:before{content:'\e0a6'}.oi-pie-chart:before{content:'\e0a7'}.oi-pin:before{content:'\e0a8'}.oi-play-circle:before{content:'\e0a9'}.oi-plus:before{content:'\e0aa'}.oi-power-standby:before{content:'\e0ab'}.oi-print:before{content:'\e0ac'}.oi-project:before{content:'\e0ad'}.oi-pulse:before{content:'\e0ae'}.oi-puzzle-piece:before{content:'\e0af'}.oi-question-mark:before{content:'\e0b0'}.oi-rain:before{content:'\e0b1'}.oi-random:before{content:'\e0b2'}.oi-reload:before{content:'\e0b3'}.oi-resize-both:before{content:'\e0b4'}.oi-resize-height:before{content:'\e0b5'}.oi-resize-width:before{content:'\e0b6'}.oi-rss-alt:before{content:'\e0b7'}.oi-rss:before{content:'\e0b8'}.oi-script:before{content:'\e0b9'}.oi-share-boxed:before{content:'\e0ba'}.oi-share:before{content:'\e0bb'}.oi-shield:before{content:'\e0bc'}.oi-signal:before{content:'\e0bd'}.oi-signpost:before{content:'\e0be'}.oi-sort-ascending:before{content:'\e0bf'}.oi-sort-descending:before{content:'\e0c0'}.oi-spreadsheet:before{content:'\e0c1'}.oi-star:before{content:'\e0c2'}.oi-sun:before{content:'\e0c3'}.oi-tablet:before{content:'\e0c4'}.oi-tag:before{content:'\e0c5'}.oi-tags:before{content:'\e0c6'}.oi-target:before{content:'\e0c7'}.oi-task:before{content:'\e0c8'}.oi-terminal:before{content:'\e0c9'}.oi-text:before{content:'\e0ca'}.oi-thumb-down:before{content:'\e0cb'}.oi-thumb-up:before{content:'\e0cc'}.oi-timer:before{content:'\e0cd'}.oi-transfer:before{content:'\e0ce'}.oi-trash:before{content:'\e0cf'}.oi-underline:before{content:'\e0d0'}.oi-vertical-align-bottom:before{content:'\e0d1'}.oi-vertical-align-center:before{content:'\e0d2'}.oi-vertical-align-top:before{content:'\e0d3'}.oi-video:before{content:'\e0d4'}.oi-volume-high:before{content:'\e0d5'}.oi-volume-low:before{content:'\e0d6'}.oi-volume-off:before{content:'\e0d7'}.oi-warning:before{content:'\e0d8'}.oi-wifi:before{content:'\e0d9'}.oi-wrench:before{content:'\e0da'}.oi-x:before{content:'\e0db'}.oi-yen:before{content:'\e0dc'}.oi-zoom-in:before{content:'\e0dd'}.oi-zoom-out:before{content:'\e0de'} -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/samples/ServerSideblazor/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/samples/ServerSideblazor/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/samples/ServerSideblazor/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/samples/ServerSideblazor/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | @import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); 2 | 3 | html, body { 4 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 5 | } 6 | 7 | a { 8 | color: #0366d6; 9 | } 10 | 11 | .btn-primary { 12 | color: #fff; 13 | background-color: #1b6ec2; 14 | border-color: #1861ac; 15 | } 16 | 17 | app { 18 | position: relative; 19 | display: flex; 20 | flex-direction: column; 21 | } 22 | 23 | .top-row { 24 | height: 3.5rem; 25 | display: flex; 26 | align-items: center; 27 | } 28 | 29 | .main { 30 | flex: 1; 31 | } 32 | 33 | .main .top-row { 34 | background-color: #f7f7f7; 35 | border-bottom: 1px solid #d6d5d5; 36 | justify-content: flex-end; 37 | } 38 | 39 | .main .top-row > a { 40 | margin-left: 1.5rem; 41 | } 42 | 43 | .sidebar { 44 | background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); 45 | } 46 | 47 | .sidebar .top-row { 48 | background-color: rgba(0,0,0,0.4); 49 | } 50 | 51 | .sidebar .navbar-brand { 52 | font-size: 1.1rem; 53 | } 54 | 55 | .sidebar .oi { 56 | width: 2rem; 57 | font-size: 1.1rem; 58 | vertical-align: text-top; 59 | top: -2px; 60 | } 61 | 62 | .nav-item { 63 | font-size: 0.9rem; 64 | padding-bottom: 0.5rem; 65 | } 66 | 67 | .nav-item:first-of-type { 68 | padding-top: 1rem; 69 | } 70 | 71 | .nav-item:last-of-type { 72 | padding-bottom: 1rem; 73 | } 74 | 75 | .nav-item a { 76 | color: #d7d7d7; 77 | border-radius: 4px; 78 | height: 3rem; 79 | display: flex; 80 | align-items: center; 81 | line-height: 3rem; 82 | } 83 | 84 | .nav-item a.active { 85 | background-color: rgba(255,255,255,0.25); 86 | color: white; 87 | } 88 | 89 | .nav-item a:hover { 90 | background-color: rgba(255,255,255,0.1); 91 | color: white; 92 | } 93 | 94 | .content { 95 | padding-top: 1.1rem; 96 | } 97 | 98 | .navbar-toggler { 99 | background-color: rgba(255, 255, 255, 0.1); 100 | } 101 | 102 | .valid.modified:not([type=checkbox]) { 103 | outline: 1px solid #26b050; 104 | } 105 | 106 | .invalid { 107 | outline: 1px solid red; 108 | } 109 | 110 | .validation-message { 111 | color: red; 112 | } 113 | 114 | @media (max-width: 767.98px) { 115 | .main .top-row { 116 | display: none; 117 | } 118 | } 119 | 120 | @media (min-width: 768px) { 121 | app { 122 | flex-direction: row; 123 | } 124 | 125 | .sidebar { 126 | width: 250px; 127 | height: 100vh; 128 | position: sticky; 129 | top: 0; 130 | } 131 | 132 | .main .top-row { 133 | position: sticky; 134 | top: 0; 135 | } 136 | 137 | .main > div { 138 | padding-left: 2rem !important; 139 | padding-right: 1.5rem !important; 140 | } 141 | 142 | .navbar-toggler { 143 | display: none; 144 | } 145 | 146 | .sidebar .collapse { 147 | /* Never collapse the sidebar for wide screens */ 148 | display: block; 149 | } 150 | } 151 | 152 | .liquid-custom-modal { 153 | display: flex; 154 | flex-direction: column; 155 | width: 60vw; 156 | height: 60vh; 157 | background-color: #fafafa; 158 | border-radius: 12px; 159 | border: 1px solid #fff; 160 | padding: 0.5rem; 161 | z-index: 102; 162 | box-shadow: 0 2px 2px rgba(0,0,0,.75); 163 | } 164 | 165 | .liquid-prompt-modal { 166 | display: flex; 167 | flex-direction: column; 168 | width: 600px; 169 | background-color: #fefefe; 170 | border-radius: 4px; 171 | border: 1px solid #fff; 172 | padding: 0.5rem; 173 | z-index: 102; 174 | box-shadow: 0 2px 2px rgba(0,0,0,.75); 175 | } 176 | 177 | .liquid-prompt-modal .liquid-modal-dialog-header { 178 | display: none; 179 | } 180 | -------------------------------------------------------------------------------- /samples/ServerSideblazor/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/samples/ServerSideblazor/wwwroot/favicon.ico -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/screenshot.png -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Components/DataInputForm.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | @using Blazor.ModalDialog 3 | 4 | @using Microsoft.JSInterop 5 | @inject NavigationManager NavigationManager 6 | @inject IModalDialogService ModalService 7 | @inject IJSRuntime JSRuntime 8 | 9 |
10 | @if (!string.IsNullOrWhiteSpace(@Form.Description)) 11 | { 12 |
13 | @Form.Description 14 |
15 | } 16 | 17 | @for (int fieldIndex = 0; fieldIndex < this.Form.Fields.Length; fieldIndex++) 18 | { 19 | var field = this.Form.Fields[fieldIndex]; 20 | var fieldDomID = $"liquid-data-input-field-{fieldIndex}"; 21 | 22 | @if (field is DataInputFormStringField fieldString) 23 | { 24 |
25 | 26 | 32 |
33 | } 34 | else if (field is DataInputFormBoolField fieldBool) 35 | { 36 |
37 | Values[fieldBool.ID] = ui.Value.ToString()) /> 41 | 42 |
43 | } 44 | else if (field is DataInputFormIntField fieldInt) 45 | { 46 |
47 | 48 | Values[fieldInt.ID] = ui.Value.ToString()) /> 54 |
55 | } 56 | else if (field is DataInputFormEnumField fieldEnum) 57 | { 58 |
59 | 60 | 68 |
69 | } 70 | } 71 | 72 |
73 | 74 | 75 |
76 |
77 | 78 | @code { 79 | 80 | [Parameter] 81 | public ModalDataInputForm Form { get; set; } 82 | 83 | private Dictionary Values { get; } = new Dictionary(); 84 | private Dictionary DomElements = new Dictionary(); 85 | private DataInputFormField FieldWithFirstError = null; 86 | 87 | protected override void OnInitialized() 88 | { 89 | // gather the initial values 90 | foreach (var field in Form.Fields) 91 | { 92 | Values[field.ID] = field.StringValue; 93 | } 94 | } 95 | 96 | async void OK_Clicked() 97 | { 98 | // copy all the values back into the DataInputFormField's 99 | foreach (var field in this.Form.Fields) 100 | { 101 | try 102 | { 103 | field.StringValue = Values[field.ID]; 104 | } 105 | catch (Exception ex) 106 | { 107 | await ModalService.ShowMessageBoxAsync("Error", ex.Message, Blazor.ModalDialog.MessageBoxButtons.OK); 108 | await JSRuntime.Focus(DomElements[field.ID]); 109 | FieldWithFirstError = field; 110 | return; 111 | } 112 | } 113 | 114 | // validate the fields 115 | foreach (var field in this.Form.Fields) 116 | { 117 | try 118 | { 119 | field.Validate(this.Form); 120 | } 121 | catch (Exception ex) 122 | { 123 | await ModalService.ShowMessageBoxAsync("Error", ex.Message, Blazor.ModalDialog.MessageBoxButtons.OK); 124 | await JSRuntime.Focus(DomElements[field.ID]); 125 | FieldWithFirstError = field; 126 | return; 127 | } 128 | } 129 | 130 | ModalService.Close(true); 131 | } 132 | 133 | void Cancel_Clicked() 134 | { 135 | ModalService.Close(false); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Components/MessageBoxForm.razor: -------------------------------------------------------------------------------- 1 | @using Blazor.ModalDialog 2 | @using Microsoft.AspNetCore.Components.Web 3 | @inject IModalDialogService ModalDialogService 4 | 5 |
6 |
7 | @MessageText 8 |
9 | 10 |
11 | @if (GetButtonText(0) != null) 12 | { 13 | 14 | } 15 | @if (GetButtonText(1) != null) 16 | { 17 | 18 | } 19 | @if (GetButtonText(2) != null) 20 | { 21 | 22 | } 23 |
24 |
25 | 26 | 27 | @code { 28 | [Parameter] 29 | public string MessageText { get; set; } 30 | [Parameter] 31 | public MessageBoxButtons MessageButtons { get; set; } 32 | [Parameter] 33 | public MessageBoxDefaultButton DefaultButton { get; set; } 34 | 35 | private string GetButtonText(int buttonIndex) 36 | { 37 | if (buttonIndex == 0) 38 | { 39 | switch (MessageButtons) 40 | { 41 | case MessageBoxButtons.AbortRetryIgnore: return Resources.MessageBoxButtons_Abort; 42 | case MessageBoxButtons.OK: return Resources.MessageBoxButtons_OK; 43 | case MessageBoxButtons.OKCancel: return Resources.MessageBoxButtons_OK; 44 | case MessageBoxButtons.RetryCancel: return Resources.MessageBoxButtons_Retry; 45 | case MessageBoxButtons.YesNo: return Resources.MessageBoxButtons_Yes; 46 | case MessageBoxButtons.YesNoCancel: return Resources.MessageBoxButtons_Yes; 47 | case MessageBoxButtons.SaveDiscard: return Resources.MessageBoxButtons_Save; 48 | case MessageBoxButtons.SaveDiscardCancel: return Resources.MessageBoxButtons_Save; 49 | default: 50 | throw new System.ComponentModel.InvalidEnumArgumentException("MessageBoxButtons", (int)MessageButtons, typeof(MessageBoxButtons)); 51 | } 52 | } 53 | else if (buttonIndex == 1) 54 | { 55 | switch (MessageButtons) 56 | { 57 | case MessageBoxButtons.AbortRetryIgnore: return Resources.MessageBoxButtons_Retry; 58 | case MessageBoxButtons.OK: return null; 59 | case MessageBoxButtons.OKCancel: return Resources.MessageBoxButtons_Cancel; 60 | case MessageBoxButtons.RetryCancel: return Resources.MessageBoxButtons_Cancel; 61 | case MessageBoxButtons.YesNo: return Resources.MessageBoxButtons_No; 62 | case MessageBoxButtons.YesNoCancel: return Resources.MessageBoxButtons_No; 63 | case MessageBoxButtons.SaveDiscard: return Resources.MessageBoxButtons_Discard; 64 | case MessageBoxButtons.SaveDiscardCancel: return Resources.MessageBoxButtons_Discard; 65 | default: 66 | throw new System.ComponentModel.InvalidEnumArgumentException("MessageBoxButtons", (int)MessageButtons, typeof(MessageBoxButtons)); 67 | } 68 | } 69 | else if (buttonIndex == 2) 70 | { 71 | switch (MessageButtons) 72 | { 73 | case MessageBoxButtons.AbortRetryIgnore: return Resources.MessageBoxButtons_Ignore; 74 | case MessageBoxButtons.OK: return null; 75 | case MessageBoxButtons.OKCancel: return null; 76 | case MessageBoxButtons.RetryCancel: return null; 77 | case MessageBoxButtons.YesNo: return null; 78 | case MessageBoxButtons.YesNoCancel: return Resources.MessageBoxButtons_Cancel; 79 | case MessageBoxButtons.SaveDiscard: return null; 80 | case MessageBoxButtons.SaveDiscardCancel: return Resources.MessageBoxButtons_Cancel; 81 | default: 82 | throw new System.ComponentModel.InvalidEnumArgumentException("MessageBoxButtons", (int)MessageButtons, typeof(MessageBoxButtons)); 83 | } 84 | } 85 | else 86 | { 87 | throw new ArgumentOutOfRangeException("Invalid button index"); 88 | } 89 | } 90 | 91 | 92 | private string GetButtonStyle(int buttonIndex) 93 | { 94 | if (buttonIndex == 0 && this.DefaultButton == MessageBoxDefaultButton.Button1) 95 | return "btn-primary"; 96 | else if (buttonIndex == 1 && this.DefaultButton == MessageBoxDefaultButton.Button2) 97 | return "btn-primary"; 98 | else if (buttonIndex == 2 && this.DefaultButton == MessageBoxDefaultButton.Button3) 99 | return "btn-primary"; 100 | else 101 | return "btn-secondary"; 102 | } 103 | 104 | 105 | private void Button1Clicked() 106 | { 107 | MessageBoxDialogResult dialogResult; 108 | 109 | switch (this.MessageButtons) 110 | { 111 | case MessageBoxButtons.AbortRetryIgnore: dialogResult = MessageBoxDialogResult.Abort; break; 112 | case MessageBoxButtons.OK: dialogResult = MessageBoxDialogResult.OK; break; 113 | case MessageBoxButtons.OKCancel: dialogResult = MessageBoxDialogResult.OK; break; 114 | case MessageBoxButtons.RetryCancel: dialogResult = MessageBoxDialogResult.Retry; break; 115 | case MessageBoxButtons.YesNo: dialogResult = MessageBoxDialogResult.Yes; break; 116 | case MessageBoxButtons.YesNoCancel: dialogResult = MessageBoxDialogResult.Yes; break; 117 | case MessageBoxButtons.SaveDiscard: dialogResult = MessageBoxDialogResult.Save; break; 118 | case MessageBoxButtons.SaveDiscardCancel: dialogResult = MessageBoxDialogResult.Save; break; 119 | default: 120 | throw new System.ComponentModel.InvalidEnumArgumentException("MessageBoxButtons", (int)this.MessageButtons, typeof(MessageBoxButtons)); 121 | } 122 | 123 | ModalDialogParameters returnParams = new ModalDialogParameters(); 124 | returnParams.Set("MessageBoxDialogResult", dialogResult); 125 | 126 | ModalDialogService.Close(true, returnParams); 127 | } 128 | 129 | private void Button2Clicked() 130 | { 131 | MessageBoxDialogResult dialogResult; 132 | 133 | switch (this.MessageButtons) 134 | { 135 | case MessageBoxButtons.AbortRetryIgnore: dialogResult = MessageBoxDialogResult.Retry; break; 136 | //case MessageBoxButtons.OK: 137 | case MessageBoxButtons.OKCancel: dialogResult = MessageBoxDialogResult.Cancel; break; 138 | case MessageBoxButtons.RetryCancel: dialogResult = MessageBoxDialogResult.Cancel; break; 139 | case MessageBoxButtons.YesNo: dialogResult = MessageBoxDialogResult.No; break; 140 | case MessageBoxButtons.YesNoCancel: dialogResult = MessageBoxDialogResult.No; break; 141 | case MessageBoxButtons.SaveDiscard: dialogResult = MessageBoxDialogResult.Discard; break; 142 | case MessageBoxButtons.SaveDiscardCancel: dialogResult = MessageBoxDialogResult.Discard; break; 143 | default: 144 | throw new System.ComponentModel.InvalidEnumArgumentException("MessageBoxButtons", (int)this.MessageButtons, typeof(MessageBoxButtons)); 145 | } 146 | 147 | ModalDialogParameters returnParams = new ModalDialogParameters(); 148 | returnParams.Set("MessageBoxDialogResult", dialogResult); 149 | 150 | ModalDialogService.Close(true, returnParams); 151 | } 152 | 153 | private void Button3Clicked() 154 | { 155 | MessageBoxDialogResult dialogResult; 156 | 157 | switch (this.MessageButtons) 158 | { 159 | case MessageBoxButtons.AbortRetryIgnore: dialogResult = MessageBoxDialogResult.Ignore; break; 160 | //case MessageBoxButtons.OK: 161 | //case MessageBoxButtons.OKCancel: 162 | //case MessageBoxButtons.RetryCancel: 163 | //case MessageBoxButtons.YesNo: 164 | case MessageBoxButtons.YesNoCancel: dialogResult = MessageBoxDialogResult.Cancel; break; 165 | case MessageBoxButtons.SaveDiscardCancel: dialogResult = MessageBoxDialogResult.Cancel; break; 166 | default: 167 | throw new System.ComponentModel.InvalidEnumArgumentException("MessageBoxButtons", (int)this.MessageButtons, typeof(MessageBoxButtons)); 168 | } 169 | 170 | ModalDialogParameters returnParams = new ModalDialogParameters(); 171 | returnParams.Set("MessageBoxDialogResult", dialogResult); 172 | 173 | ModalDialogService.Close(true, returnParams); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/DataInputForm/DataInputFormField.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Globalization; 5 | using System.Reflection; 6 | using System.Text; 7 | 8 | namespace Blazor.ModalDialog 9 | { 10 | public abstract class DataInputFormField 11 | { 12 | internal DataInputFormField(string id) 13 | { 14 | this.ID = id; 15 | } 16 | 17 | public string ID { get; } 18 | public string Name { get; set; } 19 | public string ToolTip { get; set; } = null; 20 | 21 | internal abstract string StringValue { get; set; } 22 | internal abstract void Validate(ModalDataInputForm form); 23 | } 24 | 25 | public class DataInputFormStringField : DataInputFormField 26 | { 27 | internal DataInputFormStringField(string id) 28 | : base(id) 29 | { 30 | } 31 | public string Value { get; set; } = ""; 32 | public string PlaceholderValue { get; set; } = null; 33 | public int MinLength { get; set; } = 0; 34 | public int MaxLength { get; set; } = -1; 35 | internal override string StringValue 36 | { 37 | get { return Value; } 38 | set 39 | { 40 | this.Value = value; 41 | if (TrimWhitespace) 42 | this.Value = this.Value.Trim(); 43 | if (Truncate && MaxLength > 0) 44 | this.Value = this.Value.Substring(0, Math.Min(MaxLength, this.Value.Length)); 45 | 46 | } 47 | } 48 | public bool Truncate { get; set; } = false; 49 | public bool TrimWhitespace { get; set; } = false; 50 | 51 | /// 52 | /// 53 | /// 54 | /// null/empty string if no error. 55 | /// A string containing a description of the error. 56 | /// 57 | 58 | public Action Validator { get; set; } 59 | internal override void Validate(ModalDataInputForm form) 60 | { 61 | if (this.Value.Length < MinLength) 62 | throw new ArgumentException($"The minimum length is {MinLength}"); 63 | if (MaxLength >= 0 && this.Value.Length > MaxLength) 64 | throw new ArgumentException($"The maximum length is {MaxLength}"); 65 | this.Validator?.Invoke(this.Value, form); 66 | } 67 | } 68 | public class DataInputFormIntField : DataInputFormField 69 | { 70 | internal DataInputFormIntField(string id) 71 | : base(id) 72 | { 73 | } 74 | public int Value { get; set; } = 0; 75 | public int Min { get; set; } = int.MinValue; 76 | public int Max { get; set; } = int.MaxValue; 77 | internal override string StringValue 78 | { 79 | get { return Value.ToString(CultureInfo.InvariantCulture); } 80 | set 81 | { 82 | if (int.TryParse(value, out int intValue)) 83 | this.Value = intValue; 84 | else 85 | throw new ArgumentException("Invalid integer value"); 86 | } 87 | } 88 | 89 | public Action Validator { get; set; } 90 | internal override void Validate(ModalDataInputForm form) 91 | { 92 | if (this.Value < Min) 93 | throw new ArgumentException($"The minimum value is {Max}"); 94 | if (this.Value > Max) 95 | throw new ArgumentException($"The maximum value is {Max}"); 96 | this.Validator?.Invoke(this.Value, form); 97 | } 98 | } 99 | public class DataInputFormBoolField : DataInputFormField 100 | { 101 | internal DataInputFormBoolField(string id) 102 | : base(id) 103 | { 104 | } 105 | public bool Value { get; set; } = false; 106 | internal override string StringValue 107 | { 108 | get { return Value ? bool.TrueString : bool.FalseString; } 109 | set 110 | { 111 | if (value == bool.TrueString) 112 | this.Value = true; 113 | else if (value == bool.FalseString) 114 | this.Value = false; 115 | else 116 | throw new ArgumentException("A boolean value must be true or false"); 117 | } 118 | } 119 | 120 | public Action Validator { get; set; } 121 | internal override void Validate(ModalDataInputForm form) 122 | { 123 | this.Validator?.Invoke(this.Value, form); 124 | } 125 | } 126 | 127 | public abstract class DataInputFormEnumField : DataInputFormField 128 | { 129 | internal DataInputFormEnumField(string id) 130 | : base(id) 131 | { 132 | } 133 | public int Value { get; set; } 134 | internal abstract Type EnumType { get; } 135 | 136 | internal Tuple[] EnumValues 137 | { 138 | get 139 | { 140 | List> values = new List>(); 141 | 142 | foreach (Enum enumValue in Enum.GetValues(EnumType)) 143 | { 144 | string enumDescription = GetDescription(enumValue); 145 | int enumIntValue = ((IConvertible)enumValue).ToInt32(CultureInfo.InvariantCulture); 146 | values.Add(new Tuple(enumIntValue, enumDescription)); 147 | } 148 | 149 | return values.ToArray(); 150 | } 151 | } 152 | 153 | private static string GetDescription(T source) 154 | { 155 | FieldInfo fi = source.GetType().GetField(source.ToString()); 156 | 157 | DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes( 158 | typeof(DescriptionAttribute), false); 159 | 160 | if (attributes != null && attributes.Length > 0) 161 | return attributes[0].Description; 162 | else 163 | return source.ToString(); 164 | } 165 | } 166 | public class DataInputFormEnumField : DataInputFormEnumField 167 | where T : Enum 168 | { 169 | internal DataInputFormEnumField(string id) 170 | : base(id) 171 | { 172 | if (!typeof(T).IsEnum) 173 | throw new ArgumentException("T must be an enumerated type"); 174 | Value = (T)Enum.GetValues(typeof(T)).GetValue(0); 175 | } 176 | internal override Type EnumType { get { return typeof(T); } } 177 | public new T Value { get { return (T)Enum.ToObject(typeof(T), base.Value); } set { base.Value = ((IConvertible)value).ToInt32(CultureInfo.InvariantCulture); } } 178 | internal override string StringValue 179 | { 180 | get { return Value.ToString(); } 181 | set 182 | { 183 | this.Value = (T)Enum.Parse(typeof(T), value); 184 | } 185 | } 186 | 187 | public Action Validator { get; set; } 188 | internal override void Validate(ModalDataInputForm form) 189 | { 190 | this.Validator?.Invoke(this.Value, form); 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/LiquidModalDialogJsInterop.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using Microsoft.JSInterop; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Blazor.ModalDialog 9 | { 10 | internal static class LiquidModalDialogJsInterop 11 | { 12 | public static ValueTask Prompt(this IJSRuntime jsRuntime, string message, string defaultValue = null) 13 | { 14 | // Implemented in exampleJsInterop.js 15 | return jsRuntime.InvokeAsync( 16 | "liquidModalDialog.showPrompt", 17 | message, 18 | defaultValue); 19 | } 20 | 21 | public static async Task Focus(this IJSRuntime jsRuntime, ElementReference elementRef) 22 | { 23 | await jsRuntime.InvokeVoidAsync( 24 | "liquidModalDialog.focusElement", elementRef); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/LiquidOpenSourcePublicKey.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LiquidTechnologies/blazor-modal-dialog/10d29e4a445a2587e8efe5a3367e5aeddd7ee2e7/src/LiquidTechnologies.Blazor.ModalDialog/LiquidOpenSourcePublicKey.snk -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/LiquidTechnologies.Blazor.ModalDialog.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 3.0 6 | Blazor.ModalDialog 7 | 8 | Simon Sprott 9 | Liquid Technologies Ltd 10 | Copyright 2019 (c) Liquid Technologies. All rights reserved. 11 | MIT 12 | https://github.com/LiquidTechnologies/blazor-modal-dialog 13 | blazor-modal-dialog.png 14 | https://github.com/LiquidTechnologies/blazor-modal-dialog 15 | git 16 | Blazor Razor Components Modal Dialogue MessageBox Async Dialog 17 | Turns a Blazor Component into a Modal Dialog. Async methods allow dialogs to return values. Allows nested dialogs (i.e. a dialog can open a child dialog). Supports Blazor WebAssembly and Server. Includes Windows style Message Box for quick user feedback. 18 | true 19 | 0.9.7 20 | true 21 | LiquidOpenSourcePublicKey.snk 22 | false 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | True 48 | 49 | 50 | 51 | 52 | 53 | 54 | True 55 | True 56 | Resources.resx 57 | 58 | 59 | 60 | 61 | 62 | ResXFileCodeGenerator 63 | Resources.Designer.cs 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/MessageBox/MessageBoxButtons.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Blazor.ModalDialog 6 | { 7 | public enum MessageBoxButtons 8 | { 9 | /// 10 | /// Specifies that the 11 | /// message box contains an OK button. This field is 12 | /// constant. 13 | /// 14 | OK = 0x00000000, 15 | 16 | /// 17 | /// Specifies that the 18 | /// message box contains OK and Cancel buttons. This field 19 | /// is 20 | /// constant. 21 | /// 22 | OKCancel = 0x00000001, 23 | 24 | /// 25 | /// Specifies that the 26 | /// message box contains Abort, Retry, and Ignore buttons. 27 | /// This field is 28 | /// constant. 29 | /// 30 | AbortRetryIgnore = 0x00000002, 31 | 32 | /// 33 | /// Specifies that the 34 | /// message box contains Yes, No, and Cancel buttons. This 35 | /// field is 36 | /// constant. 37 | /// 38 | YesNoCancel = 0x00000003, 39 | 40 | /// 41 | /// Specifies that the 42 | /// message box contains Yes and No buttons. This field is 43 | /// constant. 44 | /// 45 | YesNo = 0x00000004, 46 | 47 | /// 48 | /// Specifies that the 49 | /// message box contains Retry and Cancel buttons. This field 50 | /// is 51 | /// constant. 52 | /// 53 | RetryCancel = 0x00000005, 54 | SaveDiscard, 55 | SaveDiscardCancel, 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/MessageBox/MessageBoxDefaultButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Blazor.ModalDialog 6 | { 7 | public enum MessageBoxDefaultButton 8 | { 9 | /// 10 | /// 11 | /// 12 | Button1, 13 | Button2, 14 | Button3, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/MessageBox/MessageBoxDialogResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Blazor.ModalDialog 6 | { 7 | /// 8 | /// Specifies identifiers to 9 | /// indicate the return value of a dialog box. 10 | /// 11 | public enum MessageBoxDialogResult 12 | { 13 | /// 14 | /// Nothing is returned from the dialog box. This 15 | /// means that the modal dialog continues running. 16 | /// 17 | None = 0, 18 | 19 | /// 20 | /// The 21 | /// dialog box return value is 22 | /// OK (usually sent from a button labeled OK). 23 | /// 24 | OK = 1, 25 | 26 | /// 27 | /// The 28 | /// dialog box return value is Cancel (usually sent 29 | /// from a button labeled Cancel). 30 | /// 31 | Cancel = 2, 32 | 33 | /// 34 | /// The dialog box return value is 35 | /// Abort (usually sent from a button labeled Abort). 36 | /// 37 | Abort = 3, 38 | 39 | /// 40 | /// The dialog box return value is 41 | /// Retry (usually sent from a button labeled Retry). 42 | /// 43 | Retry = 4, 44 | 45 | /// 46 | /// The 47 | /// dialog box return value is Ignore (usually sent 48 | /// from a button labeled Ignore). 49 | /// 50 | Ignore = 5, 51 | 52 | /// 53 | /// The dialog box return value is 54 | /// Yes (usually sent from a button labeled Yes). 55 | /// 56 | Yes = 6, 57 | 58 | /// 59 | /// The dialog box return value is 60 | /// No (usually sent from a button labeled No). 61 | /// 62 | No = 7, 63 | Save, 64 | Discard, 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/ModalDataInputForm.cs: -------------------------------------------------------------------------------- 1 | using Blazor.ModalDialog; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Blazor.ModalDialog 9 | { 10 | public class ModalDataInputForm 11 | { 12 | private List _fields = new List(); 13 | 14 | public ModalDataInputForm(string title, string description = "") 15 | { 16 | this.Title = title; 17 | this.Description = description; 18 | } 19 | 20 | /// 21 | /// The title of the Data Input Form 22 | /// 23 | public string Title { get; set; } 24 | /// 25 | /// The description shown above the Input Form (can be empty if not required) 26 | /// 27 | public string Description { get; set; } 28 | 29 | /// 30 | /// All the fields that will be displayed for editing 31 | /// 32 | public DataInputFormField[] Fields { get { return _fields.ToArray(); } } 33 | 34 | /// 35 | /// Get a specific field from the form 36 | /// 37 | /// 38 | /// 39 | public DataInputFormField this[string fieldID] 40 | { 41 | get 42 | { 43 | return _fields.FirstOrDefault(f => f.ID == fieldID); 44 | } 45 | } 46 | 47 | #region AddStringField 48 | /// 49 | /// Adds a field to the Data Input Form 50 | /// 51 | /// The id of the field. This must be unique within the . Used to identify the field 52 | /// The name of the field as displayed to the user 53 | /// The initial value of the field (pre-populated in the TextBox input control) 54 | /// The tooltip displayed over the TextBox input control 55 | /// If the TextBox input control is empty this value is displayed in ghosted text 56 | /// The minimum length of the string 57 | /// The maximum length of the input string (-1 for no limit) 58 | /// Removes any leading and tailing whitespace from the value the user enters (If the user entered " X " the would be "X"). 59 | /// Silently removes any data after the character (any trimming is performed first if is set). 60 | /// 61 | /// A validation function used to check the field is valid before the form is submitted. 62 | /// The first argument is the value entered by the user, the second value is the 63 | /// which provides access to all the other fields on the form in order to provide cross field validation. 64 | /// 65 | /// (v,frm) => {if (v.Contains('s')) throw new ArgumentException("String can not contain an 's'"); 66 | /// 67 | /// 68 | /// The new object, the returned value can be accessed from this via the 69 | /// property when the form is submitted. 70 | public DataInputFormStringField AddStringField( 71 | string id, string name, string initialValue, string tooltip = "", 72 | string placeholderText = "", int minLength = 0, int maxLength = -1, 73 | bool truncate = false, bool trimWhitespace = false, 74 | Action validator = null) 75 | { 76 | if (_fields.Any(f => f.ID == id)) 77 | throw new ArgumentException("Duplicate field 'id'", nameof(id)); 78 | 79 | var newField = new DataInputFormStringField(id) 80 | { 81 | Name = name, 82 | Value = initialValue, 83 | ToolTip = tooltip, 84 | PlaceholderValue = placeholderText, 85 | MinLength = minLength, 86 | MaxLength = maxLength, 87 | TrimWhitespace = trimWhitespace, 88 | Truncate = truncate, 89 | Validator = validator 90 | }; 91 | _fields.Add(newField); 92 | 93 | return newField; 94 | } 95 | #endregion 96 | 97 | #region AddIntField 98 | /// 99 | /// Adds a field to the Data Input Form 100 | /// 101 | /// The id of the field. This must be unique within the . Used to identify the field 102 | /// The name of the field as displayed to the user 103 | /// The initial value of the field (pre-populated in the TextBox input control) 104 | /// The tooltip displayed over the TextBox input control 105 | /// The minimum length of the string 106 | /// The maximum length of the input string (-1 for no limit) 107 | /// 108 | /// A validation function used to check the field is valid before the form is submitted. 109 | /// The first argument is the value entered by the user, the second value is the 110 | /// which provides access to all the other fields on the form in order to provide cross field validation. 111 | /// 112 | /// (v,frm) => {if (v == 7) throw new ArgumentException("value can not be 7"); 113 | /// 114 | /// 115 | /// The new object, the returned value can be accessed from this via the 116 | /// property when the form is submitted. 117 | public DataInputFormIntField AddIntField( 118 | string id, string name, int initialValue, string tooltip = "", 119 | int min = int.MinValue, int max = int.MaxValue, 120 | Action validator = null) 121 | { 122 | if (_fields.Any(f => f.ID == id)) 123 | throw new ArgumentException("Duplicate field 'id'", nameof(id)); 124 | 125 | var newField = new DataInputFormIntField(id) 126 | { 127 | Name = name, 128 | Value = initialValue, 129 | ToolTip = tooltip, 130 | Min = min, 131 | Max = max, 132 | Validator = validator 133 | }; 134 | _fields.Add(newField); 135 | 136 | return newField; 137 | } 138 | #endregion 139 | 140 | #region AddBoolField 141 | /// 142 | /// Adds a field to the Data Input Form 143 | /// 144 | /// The id of the field. This must be unique within the . Used to identify the field 145 | /// The name of the field as displayed to the user 146 | /// The initial value of the field (pre-populated in the TextBox input control) 147 | /// The tooltip displayed over the TextBox input control 148 | /// 149 | /// A validation function used to check the field is valid before the form is submitted. 150 | /// The first argument is the value entered by the user, the second value is the 151 | /// which provides access to all the other fields on the form in order to provide cross field validation. 152 | /// 153 | /// (v,frm) => {if (v.Contains('s')) throw new ArgumentException("String can not contain an 's'"); 154 | /// 155 | /// 156 | /// The new object, the returned value can be accessed from this via the 157 | /// property when the form is submitted. 158 | public DataInputFormBoolField AddBoolField( 159 | string id, string name, bool initialValue, string tooltip = "", 160 | Action validator = null) 161 | { 162 | if (_fields.Any(f => f.ID == id)) 163 | throw new ArgumentException("Duplicate field 'id'", nameof(id)); 164 | 165 | var newField = new DataInputFormBoolField(id) 166 | { 167 | Name = name, 168 | Value = initialValue, 169 | ToolTip = tooltip, 170 | Validator = validator 171 | }; 172 | _fields.Add(newField); 173 | 174 | return newField; 175 | } 176 | #endregion 177 | 178 | #region AddEnumField 179 | /// 180 | /// Adds a field to the Data Input Form (where is an enumerated value) 181 | /// 182 | /// The id of the field. This must be unique within the . Used to identify the field 183 | /// The name of the field as displayed to the user 184 | /// The initial value of the field (pre-populated in the TextBox input control) 185 | /// The tooltip displayed over the TextBox input control 186 | /// If the TextBox input control is empty this value is displayed in ghosted text 187 | /// The minimum length of the string 188 | /// The maximum length of the input string (-1 for no limit) 189 | /// 190 | /// A validation function used to check the field is valid before the form is submitted. 191 | /// The first argument is the value entered by the user, the second value is the 192 | /// which provides access to all the other fields on the form in order to provide cross field validation. 193 | /// 194 | /// (v,frm) => {if (v.Contains('s')) throw new ArgumentException("String can not contain an 's'"); 195 | /// 196 | /// 197 | /// The new object, the returned value can be accessed from this via the 198 | /// property when the form is submitted. 199 | public DataInputFormEnumField AddEnumField( 200 | string id, string name, T initialValue, string tooltip = "", 201 | string placeholderText = "", int minLength = 0, int maxLength = -1, 202 | Action validator = null) 203 | where T : Enum 204 | { 205 | if (_fields.Any(f => f.ID == id)) 206 | throw new ArgumentException("Duplicate field 'id'", nameof(id)); 207 | 208 | var newField = new DataInputFormEnumField(id) 209 | { 210 | Name = name, 211 | Value = initialValue, 212 | ToolTip = tooltip, 213 | Validator = validator 214 | }; 215 | _fields.Add(newField); 216 | 217 | return newField; 218 | } 219 | #endregion 220 | 221 | #region ShowAsync 222 | /// 223 | /// Shows the Data Input Form in a modal dialog container. 224 | /// 225 | /// The Modal Dialog Service 226 | /// options that affect how the dialog behaves (can be null) 227 | /// 228 | /// false if the user cancelled for form. 229 | /// true if the user completed the form (including any validation) 230 | /// The values the user entered are in the that were created with the AddXXField methods 231 | /// 232 | public async Task ShowAsync(IModalDialogService modalDialogService, ModalDialogOptions options = null) 233 | { 234 | if (modalDialogService == null) throw new ArgumentNullException(nameof(modalDialogService)); 235 | ModalDialogParameters mParams = new ModalDialogParameters(); 236 | mParams.Add("Form", this); 237 | 238 | var result = await modalDialogService.ShowDialogAsync(this.Title, options, mParams); 239 | return result.Success; 240 | } 241 | #endregion 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/ModalDialogContainer.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | @implements IDisposable 3 | @inject Blazor.ModalDialog.IModalDialogService DialogService 4 | 5 | @foreach (Blazor.ModalDialog.ModalDialogModel modalDialogEntry in DialogService.ModalDialogFrames.Reverse()) 6 | { 7 | 10 | } 11 | 12 | @code { 13 | protected override void OnInitialized() 14 | { 15 | DialogService.Changed += StateHasChanged; 16 | } 17 | 18 | public void Dispose() 19 | { 20 | DialogService.Changed -= StateHasChanged; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/ModalDialogFrameView.razor: -------------------------------------------------------------------------------- 1 | @inherits ModalDialogFrameViewBase 2 | @using Microsoft.AspNetCore.Components.Web 3 | 4 |
5 |
6 | 7 |
8 |
9 |
10 |

@Title

11 | @if (ModalDialogEntry.Options.ShowCloseButton) 12 | { 13 | 16 | } 17 |
18 |
19 | 20 | @ModalDialogEntry.DialogContents 21 | 22 |
23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/ModalDialogFrameView.razor.cs: -------------------------------------------------------------------------------- 1 | using Blazor.ModalDialog; 2 | using Microsoft.AspNetCore.Components; 3 | using Microsoft.AspNetCore.Components.Web; 4 | using System; 5 | using System.Diagnostics; 6 | 7 | namespace Blazor.ModalDialog 8 | { 9 | public class ModalDialogFrameViewBase : ComponentBase 10 | { 11 | 12 | [Parameter] 13 | public ModalDialogModel ModalDialogEntry { get; set; } 14 | 15 | [Parameter] 16 | public string Title { get; set; } 17 | 18 | [Inject] protected IModalDialogService DialogService { get; set; } 19 | 20 | protected void HandleBackgroundClick() 21 | { 22 | if (ModalDialogEntry.Options.BackgroundClickToClose) 23 | DialogService.Close(false); 24 | } 25 | 26 | //protected void HandleBackgroundKeyPress(KeyboardEventArgs args) 27 | //{ 28 | // if (ModalDialogEntry.Options.EscapeKeyToClose && args.Key == "escape") 29 | // DialogService.Close(false); 30 | //} 31 | 32 | 33 | protected void HandleCloseBtnClick() 34 | { 35 | DialogService.Close(false); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Blazor.ModalDialog { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Blazor.ModalDialog.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Abort. 65 | /// 66 | internal static string MessageBoxButtons_Abort { 67 | get { 68 | return ResourceManager.GetString("MessageBoxButtons_Abort", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Cancel. 74 | /// 75 | internal static string MessageBoxButtons_Cancel { 76 | get { 77 | return ResourceManager.GetString("MessageBoxButtons_Cancel", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to Discard. 83 | /// 84 | internal static string MessageBoxButtons_Discard { 85 | get { 86 | return ResourceManager.GetString("MessageBoxButtons_Discard", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to Ignore. 92 | /// 93 | internal static string MessageBoxButtons_Ignore { 94 | get { 95 | return ResourceManager.GetString("MessageBoxButtons_Ignore", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// Looks up a localized string similar to No. 101 | /// 102 | internal static string MessageBoxButtons_No { 103 | get { 104 | return ResourceManager.GetString("MessageBoxButtons_No", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// Looks up a localized string similar to OK. 110 | /// 111 | internal static string MessageBoxButtons_OK { 112 | get { 113 | return ResourceManager.GetString("MessageBoxButtons_OK", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// Looks up a localized string similar to Retry. 119 | /// 120 | internal static string MessageBoxButtons_Retry { 121 | get { 122 | return ResourceManager.GetString("MessageBoxButtons_Retry", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// Looks up a localized string similar to Save. 128 | /// 129 | internal static string MessageBoxButtons_Save { 130 | get { 131 | return ResourceManager.GetString("MessageBoxButtons_Save", resourceCulture); 132 | } 133 | } 134 | 135 | /// 136 | /// Looks up a localized string similar to Yes. 137 | /// 138 | internal static string MessageBoxButtons_Yes { 139 | get { 140 | return ResourceManager.GetString("MessageBoxButtons_Yes", resourceCulture); 141 | } 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Abort 122 | 123 | 124 | Cancel 125 | 126 | 127 | Discard 128 | 129 | 130 | Ignore 131 | 132 | 133 | No 134 | 135 | 136 | OK 137 | 138 | 139 | Retry 140 | 141 | 142 | Save 143 | 144 | 145 | Yes 146 | 147 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Blazor.ModalDialog 4 | { 5 | public static class ServiceCollectionExtensions 6 | { 7 | public static IServiceCollection AddModalDialog(this IServiceCollection services) 8 | { 9 | return services.AddScoped(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Services/IModalDialogService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Blazor.ModalDialog 8 | { 9 | public interface IModalDialogService 10 | { 11 | /// 12 | /// A list of all the modal dialogs that are currently open 13 | /// 14 | IEnumerable ModalDialogFrames { get; } 15 | 16 | /// 17 | /// Shows a modal dialog built from the specified Blazor component . 18 | /// 19 | /// Type of the Blazor component to display. 20 | /// Modal Dialog title 21 | /// 22 | /// Options to configure the Modal Dialog. 23 | /// If null then default options are used 24 | /// 25 | /// 26 | /// Key/Value collection of parameters to pass to Blazor component being displayed. 27 | /// These are accessible within the Blazor Components via a [Parameter] properties i.e. 28 | /// 29 | /// [Parameter] public int FormId { get; set; } 30 | /// 31 | /// If null then an empty object is passed to the Blazor Component 32 | /// 33 | /// 34 | /// A task that is completed when the Modal Dialog has been d. 35 | /// The value contained in the task indicates success (as set by the defined by 36 | /// when it closes the dialog) and contains the return parameters. 37 | /// 38 | /// 39 | /// Shows the Blazor Component as a Modal Dialog. 40 | /// 41 | /// The should call the to close the Modal Dialog. 42 | /// 43 | /// This is typically called from an async function. The use of await in the returned task will cause execution to continue when the 44 | /// modal dialog is closed. 45 | /// 46 | /// 47 | /// 48 | /// async void ShowModal() 49 | /// { 50 | /// // Arguments can be passed into the modal dialog 51 | /// var parameters = new ModalDialogParameters(); 52 | /// parameters.Add("FormId", 11); 53 | /// 54 | /// // using await will cause execution to resume when the dialog has been closed. 55 | /// ModalDialogResult result = await ModalDialog.ShowDialogAsync<SignUpForm>("Sign Up Form", null, parameters); 56 | /// if (result.Success) 57 | /// CreateNewUser(result.ReturnParameters.Get<string>("FirstName"), result.ReturnParameters.Get<string>("LastName")); 58 | /// } 59 | /// 60 | /// 61 | Task ShowDialogAsync(string title, ModalDialogOptions options = null, ModalDialogParameters parameters = null) where TBlazorComponent : ComponentBase; 62 | 63 | /// 64 | /// Shows a modal dialog built from the specified Blazor component . 65 | /// 66 | /// Type of the Blazor component to display (must derive from . 67 | /// Modal Dialog title 68 | /// 69 | /// Options to configure the Modal Dialog. 70 | /// If null then default options are used 71 | /// 72 | /// 73 | /// Key/Value collection of parameters to pass to Blazor component being displayed. 74 | /// These are accessible within the Blazor Components via [Parameter] properties i.e. 75 | /// 76 | /// [Parameter] public int FormId { get; set; } 77 | /// 78 | /// If null then an empty object is passed to the Blazor Component 79 | /// 80 | /// 81 | /// A task that is completed when the Modal Dialog has been d. 82 | /// The value contained in the task indicates success (as set by the defined by 83 | /// when it closes the dialog) and contains the return parameters. 84 | /// 85 | /// 86 | /// Shows the Blazor Component as a Modal Dialog. 87 | /// 88 | /// The should call the to close the Modal Dialog. 89 | /// 90 | /// This is typically called from an async function. The use of await in the returned task will cause execution to continue when the 91 | /// modal dialog is closed. 92 | /// 93 | /// 94 | /// 95 | /// async void ShowModal() 96 | /// { 97 | /// // Arguments can be passed into the modal dialog 98 | /// var parameters = new ModalDialogParameters(); 99 | /// parameters.Add("FormId", 11); 100 | /// 101 | /// // using await will cause execution to resume when the dialog has been closed. 102 | /// ModalDialogResult result = await ModalDialog.ShowDialogAsync<SignUpForm>("Sign Up Form", null, parameters); 103 | /// if (result.Success) 104 | /// CreateNewUser(result.ReturnParameters.Get<string>("FirstName"), result.ReturnParameters.Get<string>("LastName")); 105 | /// } 106 | /// 107 | /// 108 | /// 109 | /// 110 | Task ShowDialogAsync(Type dialogComponentType, string title, ModalDialogOptions options = null, ModalDialogParameters parameters = null); 111 | 112 | /// 113 | /// Opens a message box as a modal dialog. 114 | /// 115 | /// The title heading of message box 116 | /// The message within the message box 117 | /// The buttons that will be displayed on the message box 118 | /// The button that will be the 'selected' one. 119 | /// The button that is clicked. 120 | /// 121 | /// If the allows 'Cancel' then clicking on the close X button or the background is the same as pressing the cancel button. 122 | /// If the does not allow 'Cancel' then there is no close X button and clicking on the background does nothing (a button must be pressed to close the dialog). 123 | /// 124 | /// TODO : make the return key select the , make the escape key act as cancel where applicable. 125 | /// 126 | /// 127 | /// 128 | /// async void ShowMessageBox() 129 | /// { 130 | /// // using await will cause execution to resume when the dialog has been closed. 131 | /// MessageBoxDialogResult dialogResult = await ModalDialog.ShowMessageBoxAsync("Confirm", "Delete All Files?", MessageBoxButtons.YesNo, MessageBoxDefaultButton.MessageBoxDefaultButton2); 132 | /// if (dialogResult == MessageBoxDialogResult.Yes) 133 | /// DeleteAllFiles(); 134 | /// } 135 | /// 136 | /// 137 | /// 138 | /// 139 | Task ShowMessageBoxAsync(string title, string message, MessageBoxButtons buttons = MessageBoxButtons.OK, MessageBoxDefaultButton defaultButton = MessageBoxDefaultButton.Button1); 140 | 141 | /// 142 | /// Closes the topmost Modal Dialog 143 | /// 144 | /// 145 | /// Indicates if the action performed by the dialog was a success. 146 | /// The exact meaning of this is specific to the dialog, but typically false means the action was cancelled, 147 | /// true means it completed OK, and an exception should have been raised if there was an error. 148 | /// 149 | /// Optional return parameters (as name value pairs) 150 | /// 151 | /// Should only be called from within an open Modal Dialog's Blazor Component. 152 | /// Should only be called once for each open Modal Dialog's Blazor Component. 153 | /// 154 | /// 155 | /// @inject IModalDialogService ModalDialogService 156 | /// 157 | ///
158 | /// 159 | ///
160 | /// 161 | /// 162 | ///
163 | /// 164 | ///
165 | /// 166 | /// 167 | ///
168 | /// 169 | /// 170 | /// 171 | ///
172 | /// 173 | /// 174 | /// @code { 175 | /// 176 | /// [Parameter] 177 | /// public string FirstName { get; set; } 178 | /// [Parameter] 179 | /// public string LastName { get; set; } 180 | /// 181 | /// async void Ok_Clicked() 182 | /// { 183 | /// try 184 | /// { 185 | /// if (string.IsNullOrWhiteSpace(FirstName) && string.IsNullOrWhiteSpace(LastName)) 186 | /// { 187 | /// ModalDialogResult result = await ModalDialogService.ShowDialogAsync("Validation Errors"); 188 | /// if (result.Success == false) 189 | /// ModalDialogService.Close(false); 190 | /// } 191 | /// else 192 | /// { 193 | /// ModalDialogParameters resultParameters = new ModalDialogParameters(); 194 | /// resultParameters.Set("FirstName", FirstName); 195 | /// resultParameters.Set("LastName", LastName); 196 | /// resultParameters.Set("FullName", FirstName + " " + LastName); 197 | /// ModalDialogService.Close(true, resultParameters); 198 | /// } 199 | /// } 200 | /// catch (Exception ex) 201 | /// { 202 | /// // pass the exception back to the ShowDialogAsync call that opened the Dialog 203 | /// ModalDialogService.Close(ex); 204 | /// } 205 | /// } 206 | /// 207 | /// void Cancel_Clicked() 208 | /// { 209 | /// ModalDialogService.Close(false); 210 | /// } 211 | /// } 212 | /// 213 | ///
214 | void Close(bool success, ModalDialogParameters returnParameters = null); 215 | 216 | /// 217 | /// Closes the topmost Modal Dialog, as the result of an error 218 | /// 219 | /// 220 | /// The exception that will be reported back to the code that Opened the Modal Dialog. 221 | /// 222 | /// 223 | /// Should only be called from within an open Modal Dialog's Blazor Component. 224 | /// Should only be called once for each open Modal Dialog's Blazor Component. 225 | /// 226 | /// 227 | /// @inject IModalDialogService ModalDialogService 228 | /// 229 | ///
230 | /// 231 | ///
232 | /// 233 | /// 234 | ///
235 | /// 236 | ///
237 | /// 238 | /// 239 | ///
240 | /// 241 | /// 242 | /// 243 | ///
244 | /// 245 | /// 246 | /// @code { 247 | /// 248 | /// [Parameter] 249 | /// public string FirstName { get; set; } 250 | /// [Parameter] 251 | /// public string LastName { get; set; } 252 | /// 253 | /// async void Ok_Clicked() 254 | /// { 255 | /// try 256 | /// { 257 | /// if (string.IsNullOrWhiteSpace(FirstName) && string.IsNullOrWhiteSpace(LastName)) 258 | /// { 259 | /// ModalDialogResult result = await ModalDialogService.ShowDialogAsync("Validation Errors"); 260 | /// if (result.Success == false) 261 | /// ModalDialogService.Close(false); 262 | /// } 263 | /// else 264 | /// { 265 | /// ModalDialogParameters resultParameters = new ModalDialogParameters(); 266 | /// resultParameters.Set("FirstName", FirstName); 267 | /// resultParameters.Set("LastName", LastName); 268 | /// resultParameters.Set("FullName", FirstName + " " + LastName); 269 | /// ModalDialogService.Close(true, resultParameters); 270 | /// } 271 | /// } 272 | /// catch (Exception ex) 273 | /// { 274 | /// // pass the exception back to the ShowDialogAsync call that opened the Dialog 275 | /// ModalDialogService.Close(ex); 276 | /// } 277 | /// } 278 | /// 279 | /// void Cancel_Clicked() 280 | /// { 281 | /// ModalDialogService.Close(false); 282 | /// } 283 | /// } 284 | /// 285 | ///
286 | void Close(Exception error); 287 | 288 | /// 289 | /// An event that indicates has changed 290 | /// 291 | event Action Changed; 292 | } 293 | } 294 | 295 | 296 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Services/ModalDialogModel.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Blazor.ModalDialog 8 | { 9 | public class ModalDialogModel 10 | { 11 | public ModalDialogModel(Type dialogComponentType, string title, ModalDialogParameters parameters, ModalDialogOptions options) 12 | { 13 | this.TaskSource = new TaskCompletionSource(); 14 | this.DialogComponentType = dialogComponentType; 15 | this.Title = title; 16 | this.Parameters = parameters; 17 | this.Options = options; 18 | } 19 | 20 | private Type DialogComponentType { get; } 21 | internal TaskCompletionSource TaskSource { get; } 22 | 23 | public Task Task { get { return this.TaskSource.Task; } } 24 | public string Title{ get; } 25 | public ModalDialogParameters Parameters { get; } 26 | public ModalDialogOptions Options { get; } 27 | 28 | public RenderFragment DialogContents 29 | { 30 | get 31 | { 32 | RenderFragment content = new RenderFragment(x => 33 | { 34 | int seq = 1; 35 | x.OpenComponent(seq++, DialogComponentType); 36 | foreach (var parameter in Parameters) 37 | x.AddAttribute(seq++, parameter.Key, parameter.Value); 38 | x.CloseComponent(); 39 | }); 40 | return content; 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Services/ModalDialogOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Blazor.ModalDialog 6 | { 7 | public class ModalDialogOptions 8 | { 9 | /// 10 | /// The position of the Modal Dialog 11 | /// 12 | /// 13 | public string Position { get; set; } = ModalDialogPositionOptions.Default; 14 | /// 15 | /// The css style applied to the modal dialog 16 | /// 17 | /// 18 | public string Style { get; set; } = ModalDialogStyleOptions.Default; 19 | /// 20 | /// The title of the modal dialog 21 | /// 22 | public string Title { get; set; } 23 | /// 24 | /// Indicates of the dialog should show a Close X in the top right 25 | /// 26 | public bool ShowCloseButton { get; set; } = true; 27 | /// 28 | /// Indicates of the dialog should automatically Close is a click is performed outside of the dialog (in the background) 29 | /// 30 | public bool BackgroundClickToClose { get; set; } = true; 31 | // public bool EscapeKeyToClose { get; set; } = true; 32 | } 33 | 34 | public static class ModalDialogStyleOptions 35 | { 36 | public const string Default = Dialog; 37 | 38 | public const string Dialog = "liquid-modal-dialog"; 39 | } 40 | public static class ModalDialogPositionOptions 41 | { 42 | public const string Center = "liquid-modal-dialog-center"; 43 | public const string TopLeft = "liquid-modal-dialog-topleft"; 44 | public const string TopRight = "liquid-modal-dialog-topright"; 45 | public const string BottomLeft = "liquid-modal-dialog-bottomleft"; 46 | public const string BottomRight = "liquid-modal-dialog-bottomright"; 47 | public const string Default = Center; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Services/ModalDialogParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Blazor.ModalDialog 6 | { 7 | public class ModalDialogParameters : Dictionary 8 | { 9 | /// 10 | /// Gets a parameter of a given type (either succeeds or throws, never returns an invalid value) 11 | /// 12 | /// The expected type of the parameter value 13 | /// The name of the parameter to retrieve the value for 14 | /// The value of the requested 15 | /// If the parameter does not exist (consider using ) 16 | /// If the parameter exists but is of the wrong type () 17 | public T Get(string parameterName) 18 | { 19 | if (!this.ContainsKey(parameterName)) 20 | { 21 | throw new KeyNotFoundException($"{parameterName} does not exist in modal parameters"); 22 | } 23 | 24 | return (T)this[parameterName]; 25 | } 26 | 27 | /// 28 | /// Gets a parameter of a given type, uses the if the parameter does not exist 29 | /// (either succeeds or throws, never returns an invalid value) 30 | /// 31 | /// The expected type of the parameter value 32 | /// The name of the parameter to retrieve the value for 33 | /// If a parameter does not exist then this value is returned instead 34 | /// The value of the requested (or the if its not in the collection 35 | /// If the parameter exists but is of the wrong type () 36 | public T Get(string parameterName, T defaultValue) 37 | { 38 | if (!TryGetValue(parameterName, out object parameterValue)) 39 | { 40 | parameterValue = defaultValue; 41 | this[parameterName] = parameterValue; 42 | } 43 | return (T)parameterValue; 44 | } 45 | 46 | /// 47 | /// Sets a value into the parameter collection 48 | /// 49 | /// The type of the being stored 50 | /// The name of the parameter (if it already exists it will be overwritten) 51 | /// The value to be associated with the 52 | public void Set(string parameterName, T parameterValue) 53 | { 54 | this[parameterName] = parameterValue; 55 | } 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Services/ModalDialogResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Blazor.ModalDialog 6 | { 7 | /// 8 | /// The results returned from a Modal Dialog 9 | /// 10 | public class ModalDialogResult 11 | { 12 | internal ModalDialogResult(bool success, ModalDialogParameters returnParameters) 13 | { 14 | this.Success = success; 15 | this.ReturnParameters = returnParameters; 16 | } 17 | /// 18 | /// Indicates if the action performed by the dialog was a success. 19 | /// The exact meaning of this is specific to the dialog, but typically false means the action was cancelled, 20 | /// true means it completed OK, and an exception should have been raised if there was an error. 21 | /// 22 | public bool Success { get; } 23 | /// 24 | /// Return parameters (as name value pairs) 25 | /// 26 | public ModalDialogParameters ReturnParameters { get; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/Services/ModalDialogService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Blazor.ModalDialog 9 | { 10 | public class ModalDialogService : IModalDialogService 11 | { 12 | private Stack _dialogs = new Stack(); 13 | 14 | public ModalDialogService() { } 15 | 16 | public Task ShowDialogAsync(string title, ModalDialogOptions options, ModalDialogParameters parameters) 17 | where TBlazorComponent : ComponentBase 18 | { 19 | return ShowDialogAsync(typeof(TBlazorComponent), title, options, parameters); 20 | } 21 | 22 | 23 | public Task ShowDialogAsync(Type dialogComponentType, string title, ModalDialogOptions options, ModalDialogParameters parameters) 24 | { 25 | if (!typeof(ComponentBase).IsAssignableFrom(dialogComponentType)) 26 | throw new ArgumentException($"{dialogComponentType.FullName} must be a Blazor Component"); 27 | 28 | parameters = parameters ?? new ModalDialogParameters(); 29 | options = options ?? new ModalDialogOptions(); 30 | 31 | ModalDialogModel newDialogWindow = new ModalDialogModel(dialogComponentType, title, parameters, options); 32 | _dialogs.Push(newDialogWindow); 33 | 34 | OnChanged(); 35 | 36 | return newDialogWindow.Task; 37 | } 38 | 39 | public async Task ShowMessageBoxAsync(string title, string message, MessageBoxButtons buttons, MessageBoxDefaultButton defaultButton) 40 | { 41 | if (buttons == MessageBoxButtons.OK && defaultButton != MessageBoxDefaultButton.Button1) throw new ArgumentException("Must be Button 1", nameof(defaultButton)); 42 | if ((buttons == MessageBoxButtons.OKCancel || buttons == MessageBoxButtons.RetryCancel || buttons == MessageBoxButtons.YesNo) && defaultButton == MessageBoxDefaultButton.Button3) throw new ArgumentException("Must be Button 1 or 2", nameof(defaultButton)); 43 | 44 | ModalDialogOptions options = new ModalDialogOptions(); 45 | if (buttons == MessageBoxButtons.YesNo || buttons == MessageBoxButtons.AbortRetryIgnore) 46 | { 47 | options.ShowCloseButton = false; 48 | options.BackgroundClickToClose = false; 49 | } 50 | 51 | ModalDialogParameters parameters = new ModalDialogParameters(); 52 | parameters.Set(nameof(Components.MessageBoxForm.MessageText), message); 53 | parameters.Set(nameof(Components.MessageBoxForm.MessageButtons), buttons); 54 | parameters.Set(nameof(Components.MessageBoxForm.DefaultButton), defaultButton); 55 | 56 | ModalDialogResult result = await ShowDialogAsync(title, options, parameters); 57 | if (result.Success == false) 58 | { 59 | Debug.Assert(buttons != MessageBoxButtons.YesNo && buttons != MessageBoxButtons.AbortRetryIgnore, "Should not be able dismiss message boxes with no cancel (except OK)"); 60 | 61 | if (buttons == MessageBoxButtons.OK) 62 | return MessageBoxDialogResult.OK; 63 | else 64 | return MessageBoxDialogResult.Cancel; 65 | } 66 | else 67 | { 68 | return result.ReturnParameters.Get("MessageBoxDialogResult"); 69 | } 70 | } 71 | 72 | public void Close(bool success, ModalDialogParameters returnParameters) 73 | { 74 | returnParameters = returnParameters ?? new ModalDialogParameters(); 75 | 76 | ModalDialogModel closingDialogWindow = _dialogs.Pop(); 77 | closingDialogWindow.TaskSource.SetResult(new ModalDialogResult(success, returnParameters)); 78 | OnChanged(); 79 | } 80 | 81 | public void Close(Exception exception) 82 | { 83 | ModalDialogModel closingDialogWindow = _dialogs.Pop(); 84 | closingDialogWindow.TaskSource.SetException(exception); 85 | OnChanged(); 86 | } 87 | 88 | 89 | public IEnumerable ModalDialogFrames { get { return _dialogs; } } 90 | 91 | 92 | public event Action Changed; 93 | protected virtual void OnChanged() 94 | { 95 | if (Changed != null) 96 | Changed(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/wwwroot/liquid-modal-dialog.css: -------------------------------------------------------------------------------- 1 | .liquid-modal-dialog-container { 2 | display: none; 3 | position: fixed; 4 | width: 100%; 5 | height: 100%; 6 | z-index: 100; 7 | } 8 | 9 | .liquid-modal-dialog-overlay { 10 | display: block; 11 | position: fixed; 12 | width: 100%; 13 | height: 100%; 14 | z-index: 101; 15 | background-color: rgba(0,0,0,0.5); 16 | } 17 | 18 | .liquid-modal-dialog-active { 19 | display: flex; 20 | } 21 | 22 | .liquid-modal-dialog { 23 | display: flex; 24 | flex-direction: column; 25 | width: 50rem; 26 | background-color: #fff; 27 | border-radius: 4px; 28 | border: 1px solid #fff; 29 | padding: 1.5rem; 30 | box-shadow: 0 2px 2px rgba(0,0,0,.25); 31 | max-height: 90vh; /*90% of the browser height*/ 32 | max-width: 90vw; /*90% of the browser width*/ 33 | } 34 | 35 | .liquid-modal-dialog-header { 36 | display: flex; 37 | align-items: flex-start; 38 | justify-content: space-between; 39 | padding: 0 0 2rem 0; 40 | } 41 | 42 | .liquid-modal-dialog-title { 43 | margin-bottom: 0; 44 | } 45 | 46 | .liquid-modal-dialog-close { 47 | padding: 1rem; 48 | margin: -1rem -1rem -1rem auto; 49 | background-color: transparent; 50 | border: 0; 51 | -webkit-appearance: none; 52 | cursor: pointer; 53 | font-size: 1.5rem; 54 | font-weight: bold; 55 | } 56 | 57 | .liquid-modal-dialog-content{ 58 | overflow:auto; 59 | padding-right:1rem; 60 | } 61 | 62 | .liquid-modal-dialog-center { 63 | align-items: center; 64 | justify-content: center; 65 | } 66 | 67 | .liquid-modal-dialog-wrapper { 68 | z-index: 102; 69 | } 70 | 71 | .liquid-modal-dialog-topleft .liquid-modal-dialog-wrapper { 72 | position: absolute; 73 | top: 32px; 74 | left: 32px; 75 | } 76 | 77 | .liquid-modal-dialog-topright .liquid-modal-dialog-wrapper { 78 | position: absolute; 79 | top: 32px; 80 | right: 32px; 81 | } 82 | 83 | .liquid-modal-dialog-bottomleft .liquid-modal-dialog-wrapper { 84 | position: absolute; 85 | bottom: 32px; 86 | left: 32px; 87 | } 88 | 89 | .liquid-modal-dialog-bottomright .liquid-modal-dialog-wrapper { 90 | position: absolute; 91 | bottom: 32px; 92 | right: 32px; 93 | } 94 | -------------------------------------------------------------------------------- /src/LiquidTechnologies.Blazor.ModalDialog/wwwroot/liquid-modal-dialog.js: -------------------------------------------------------------------------------- 1 |  2 | window.liquidModalDialog = { 3 | showPrompt: function (message, defaultValue) { 4 | return prompt(message, defaultValue); 5 | }, 6 | focusElement: function (element) { 7 | element.focus(); 8 | } 9 | }; 10 | --------------------------------------------------------------------------------