#05 Tela de assinatura com formulário DINÂMICO e MULTI-STEP | [Série] Criando um SaaS do ZERO

In this live‑coding tutorial Samuel Rezon builds the subscription (sign‑up) page of a SaaS application using Angular. He creates a reusable DynamicFormComponent that renders a multi‑step form based on a JSON configuration, covering two steps – administrator data and barbershop (company) data. The video shows how to scaffold a dedicated subscription module, define lazy‑loaded routes, and generate admin‑ and company‑detail components. Samuel integrates several third‑party tools: ngx‑mask for input masking, ngx‑nit/untilDestroy for automatic unsubscription, uuid for unique file paths, and Supabase storage accessed through a custom DownloadStoragePipe. He also builds a FormStorageDirective that syncs the form group with localStorage, ensuring data is not lost on page reload. A CEP (Brazilian postal code) autocomplete is added via the cep‑prompts library, automatically filling address fields and disabling them while the lookup is in progress. UI polish is achieved with ng‑zorro steps/cards, a custom mb‑icon directive that wraps Google Material icons, and various autofocus and accessibility tweaks. Throughout the session Samuel explains architectural decisions, refactors imported code from his own SaaS (Ministrali), fixes routing bugs, and demonstrates debugging of validation and rendering errors. The tutorial ends with a fully functional, dynamically generated, persisted, multi‑step subscription form ready for the next video where account creation will be implemented.
Chapters
vamos ver a mágica acontecendo. Então a gente tem um CEP aqui funcionando e eu vou colocar um CEP. E pronto, meus amigos, olha a mágica feita. Botei o CEP, ele já preencheu automaticamente a rua, bairro, cidade, estado, país. E aí falta só colocar o número. Então o que que essa diretiva vai fazer? Quando eu iniciar ela, quando eu importar ela em alguma página, o que que ela vai fazer? Ela vai criar um form group, ela vai no ng-onInit atualizar os valores do localStorage e vai dar um listenOnUpdate. Pra quê? Pra que quando tiver alguma alteração ele salvar isso automaticamente no localStorage. E aí, meus amigos, tudo bem com vocês? Samuel Rezon por aqui. Hoje a gente vai criar a página de assinatura do nosso SaaS. A gente vai criar um formulário de cadastro onde o usuário preenche as informações pessoais dele, depois numa próxima etapa ele preenche as informações da barbearia dele, e aí a gente vai fazer tudo isso com um formulário dinâmico e multistep e salvando essas informações no local storage sem perder essas informações. Então o usuário pode voltar e de novo recarregar a página e vai estar tudo salvo. Mas antes de começar o vídeo eu quero dizer que a gente atingiu a marca de 1000 inscritos aqui no canal e eu tô muito feliz com isso. Muito obrigado por todo o apoio, todo mundo que tá comentando, o pessoal da comunidade no WhatsApp. Se você ainda não tá participando, entra É o primeiro link aqui na descrição. Então muito obrigado, gente, vocês são demais, vocês são incríveis, e esse apoio de vocês tem me ajudado bastante a continuar produzindo esse tipo de conteúdo.
Fechou?
Vamos para o vídeo. Bom, então estamos aqui no nosso VS Code, da mesma forma que a gente parou da última vez. Eu já tô rodando o projeto aqui e eu vou abrir aqui para vocês. Então a gente tá com a nossa página de login e a nossa página de esqueci minha senha aqui funcionando normalmente. Um único detalhezinho que eu esqueci da página "Esqueci minha senha" foi que a gente errou aqui a rota, então ele não tá voltando. E eu vou mudar esse carinha aqui para o tipo link para ficar mais fácil da gente visualizar. Então quando eu venho aqui, ó, ele fica um linkzinho, quando eu clico ele volta. Então acho que essa foi uma correção que eu fiquei de fazer aqui, mas estamos na mesma página onde a gente estava, onde a gente parou. E o que que a gente vai fazer agora? A gente vai criar nosso componente de formulário dinâmico. E esse componente eu vou copiar ele do meu SaaS, o Ministrali, e eu vou colar ele aqui. A gente vai dar uma refatorada, mexer e remover algumas coisas que a gente não precisa aqui, e a gente já vai fazer esse formulário dinâmico nessa parte de login aqui. Eu vou mostrar para vocês a diferença, tá? Então a gente vai vir aqui em src, a gente vai criar uma nova pasta chamada src/app, uma nova pasta chamada widget. Como eu disse no vídeo sobre arquitetura, essa pasta normalmente eu coloco componentes, pipes e diretivas. Então widget components, aqui eu vou dar um Ctrl+V e eu já tenho todos meus arquivos aqui do meu formulário dinâmico. Eu vou remover e editar algumas coisas aqui que a gente não precisa, tá? Então aqui tem várias importações do Ministério, alguns componentes que a gente não vai precisar e que a gente não vai utilizar. Vou instalar algumas coisas que a gente precisa. Então a gente vai precisar do ngx-mask, npm install ngx-mask.
Já tô dando o npm install dele aqui.
Outra coisa que a gente vai precisar é esse carinha aqui que faz o untilDestroy, que é do ngx-nit.
Então eu vou vir aqui no meu sass, ngx-nit, untilDestroy.
Esse carinha aqui é só uma forma mais fácil da gente dar um subscribe do Angular. Então a gente usa esse OnDestroy aqui no pipe e coloca esse decorator aqui no componente. Eu gosto bastante dele, é muito simples, muito prático, muito fácil.
Mesma coisa, @ngDestroy.
Esse carinha aqui a gente não vai usar aqui. O TranslocoModule também a gente não vai usar.
HasRole também não, Product não. IconDirective a gente vai utilizar. DownloadStoragePipe também e o AutoFocusDirective. Também a gente vai utilizar, a gente vai precisar de todos eles.
Aqui eu vou mudar para MB, download storage pipe fica aqui, a gente tira esse cara, vai continuar aqui. Agora que eu já consigo importar esse carinha aqui do Until Destroy, eu vou importar esse cara aqui também.
Vamos continuar aqui, ó, isso aqui a gente vai remover. Isso aqui também a gente remove. Vou salvar.
Depois eu vou explicar para vocês toda essa parte aqui, tá bom? A gente vai precisar desse autofocus directive.
Eu vou vir aqui no meu projeto e vou copiar e colar ele aqui também. Então eu tenho uma diretiva, componentes, directives, Ctrl+V, autofocus. MB e MB.
Esse carinha vai dar um autofocus quando a gente precisar, tá, focar no formulário.
Eu tenho o download storage pipe, então eu vou pegar esse carinha aqui também. Copia, cria uma nova pasta chamada pipes, Ctrl+V, storage, storage.
Que a gente vai precisar do bucket name. Que que esse carinha aqui vai fazer, pessoal? Ele vai— esse aqui é um pipe que eu tenho para fazer o download das nossas imagens lá do Supabase. Então é uma forma que eu simplifiquei de conseguir fazer o download das imagens do Supabase só com pipe.
É bem mais simples, bem mais prático e bem mais fácil.
Então eu vou vir aqui criar uma pasta chamada denúncia.
E vou criar um bucket name, bucket_name enum.ts. Show! Export enum é bucket_name avatar. Enquanto a gente só tem esse, então é esse que a gente vai utilizar.
E a gente vai precisar também desse storage API.
Eu vou pegar ele aqui do meu projeto. Shared APIs, Storage API.
Gente, aqui é muito simples, ó, eu consigo compartilhar os códigos.
Eu tenho esse, o ID aqui que eu vou precisar instalar, npm install uuid. Esse cara eu uso para gerar um path quando eu tô inserindo, mas basicamente eu tenho Uma API, um storage API, que eu tenho um método de insert, que eu passo o arquivo, o caminho, né, desse meu arquivo.
Se ele existir, eu já deleto ele, que aí eu já gera um novo e salvo no storage do Supabase. Basicamente é isso. Se eu quiser atualizar, mesma coisa. Para fazer o download, eu faço um download. Para fazer um delete, é um delete. Gente, Supabase é maravilhoso! Com isso aqui eu já tenho um serviço que salva e busca as imagens no meu storage do Swabase.
Eu vou remover esse cara aqui e vou importar ele novamente dentro do meu projeto.
Agora eu já tenho o meu download storage pipe e agora falta o IconDirective.
IconDirective, deixa eu pegar esse carinha aqui, diretivas, IconDirective, MB.
Esse cara aqui eu costumo utilizar ele porque os ícones do ng-zorro eles não são tão completos quanto os ícones do Material. Se tem uma coisa que é boa do Material são os ícones deles, então eu gosto de utilizar. O Angular Material não gosto, mas os ícones do Material, que são os ícones da Google, são muito legais. Então acabo criando uma diretiva que eu passo o mb-icon e coloco o nome do ícone e passo os detalhes aqui. E aí o que que a gente vai precisar fazer? A gente vai precisar instalar essa biblioteca de ícones do Material. Então a gente vai vir aqui no Material Icons. Deixa eu abrir o meu navegador aqui. Esse carinha aqui, ó, é muito simples, bem prático. Vou copiar, vou instalar. E depois a gente precisa vir aqui no nosso SCSS e dar um import nele.
Basicamente é isso. Então eu vou vir aqui no meu styles Vou salvar e vou importar a biblioteca do Angular Material. Deixa eu pausar o projeto e rodar de novo.
Mas com isso aqui eu já tenho os meus ícones do Angular Material.
Show!
Eu vou importar ele aqui novamente. Esse meu componente Dynamic aqui já tá ok. Agora eu vou trabalhar aqui dentro do meu HTML. Eu vou remover esses dois carinhas aqui que eu não preciso. Que eu tô fazendo ao vivasso com vocês, tá, meus amigos? Pra ficar fácil de vocês entenderem o que que eu tô mexendo aqui.
Label, que eu posso tirar isso.
Então esse cara aqui, ó, primeiro já tá falando que ele tem que ter isso aqui. Então quando vocês tiverem esse tipo de erro, podem clicar aqui e ele vai abrir no navegador de vocês essa parte do Angular Sling aqui no GitHub e ele mostra o que que tá dando erro, o que que, como que você faz pra consertar, né? Então o que que ele tá falando esse erro aqui basicamente? Ele tem que ter um evento de uma key, né, de, se quer de acessibilidade.
Então aqui a gente vai adicionar um keypress.space. Então quando o cara pressionar espaço a gente vai fazer isso aqui e eu vou colocar um tabindex de 0, salvar e tá feito.
Se eu tirar esse carinha aqui ele tá dando outro erro, tá? Ele tá dando elements must be interactive. Isso é só porque a gente tá usando um i como ícone, tá bom?
E tá tudo certo.
Aqui não é mt-icon mais, eu vou alterar em todos, é mb-icon e mb-type.
Se não tá mb-type é porque eu não mudei aqui. Então aqui alterar para mb, perfeito. Próximo erro, mt-auto-focus, mb AutoFocus, aqui esqueceu. Próximo tem que ser associado a um form element, que eu vou dar um for field.name. Próximo, aqui embaixo, isso aqui eu posso tirar, esse aqui eu posso tirar, esses dois aqui eu posso tirar. O label aqui a mesma coisa, tá. Próximo aqui tem que ter um text alternative alt imagem. Beleza, então aqui já tá feito. Deixa eu ver se tem mais algum detalhe aqui. Aqui eu vou remover, então old storage pipe de texto unitário. Esse cara eu vou mudar para MB switch, então se você pesquisar MT switch E eu acho que é isso, pessoal, nessa parte de editar esse componente aqui.
E aí deixa eu mostrar para vocês a diferença entre utilizar esse componente, esse formulário dinâmico, e da forma que a gente utilizou aqui no nosso login. Que que eu gosto de fazer isso? Praticamente a maioria dos meus formulários no ministrário, no meu SaaS, eu uso dessa forma.
Então aqui no meu login page eu tive que fazer isso aqui, né?
Então a gente Qualquer formulário no nosso sistema a gente tem que fazer dessa forma aqui, criar o formulário aqui, fazer esse form control, cuidar de tudo isso e colocar isso aqui, esse template no HTML, fica gigante. Como que a gente vai mexer? Como que a gente vai alterar aqui? Primeira coisa, a gente vai importar o DynamicFormComponent. Importei ele, eu vou literalmente comentar isso aqui, MP DynamicFormConfig. Por enquanto eu vou passar uma vazia porque eu vou criar ela ali.
E aí aqui eu vou vir no meu, vou remover isso aqui, vou remover isso aqui, vou criar um LoginConfig, essa é DynamicFormConfig, e aqui eu vou passar o label email, name email, type field é DynamicField Bom, input type field email. Os validators eu passo tudo por aqui, então validations, SAP validators,.required email, size 24, salvei. E a senha, beleza. Show forgot password true, forgot password link é o forgot password Então vocês vão ver que praticamente agora eu vou dar um View Child aqui, Dynamic Form. Eu tenho meu form aqui, form, login_form, que vai ser a mesma coisa. Perfeito, salvei, passei o login_config aqui e agora vocês vão ver a diferença. Vamos ver que ela tá dando um erro aqui. A gente tem esse erro aqui na parte do Dynamic Form, ver isso aqui. Remover esse cara, não preciso. As roles eu não preciso, também não preciso. Salvei. Vamos ver se vai dar tudo certo. Eu tenho esse import aqui, agora ele mudou para use aqui, e eu acho que já funcionou.
Então vamos voltar lá no nosso sistema.
Eu vou ir na minha página de login. Bucket name não foi encontrado.
Deixa eu parar o projeto, rodar de novo.
Vamos ver se vai funcionar. Beleza, rodou. Beleza, ele deu aqui, ó, o ngx-mask, que eu esqueci de configurar. Então eu preciso ngx-mask, a gente vai na documentação e a gente vai pegar esse carinha aqui, abrir o app.config e chamar ele aqui. Vamos ver, vamos abrir aqui de novo. Perfeito.
Bom, parece que tá na mesma coisa, né?
Então se eu venho aqui, digito, ele já tá fazendo a validação.
Só que como vocês podem perceber, agora ele tá mostrando a mensagem de erro automaticamente. Então eu dou um A aqui, ó, o email já tá inválido,.com, a senha 123456.
Se eu tirar, ele vai tirar o campo obrigatório aqui. Aqui a mesma coisa, eu consigo ver e tirar.
Aqui ele deu um problema de ícone que ele não renderizou. Quando eu entrar, NG Zoo, quero a documentação do NG Zoo, vou vir componentes, ícone. Cá embaixo, no finalzinho, ele fala que a gente tem que colocar isso aqui, ó, para a gente renderizar os ícones dinamicamente.
Eu vou pegar a renderização aqui, esse código, vou abrir o meu VS Code, project.json, e vou colar esse carinha aqui.
Isso é uma forma de eu adicionar os ícones do ng-resolve na minha pasta assets e o sistema já conseguir encontrar esses ícones quando eu tiver utilizando.
Beleza, rodei, eu volto aqui, abriu, tá funcionando. O ícone normalmente.
E agora eu tenho a minha tela de login. Deixa eu mostrar aqui para vocês.
Aqui a gente tira tudo.
Aqui o nosso login page, agora a gente tem um formulário que tá sendo carregado dinamicamente. Simples, prático e rápido. Eu tenho os mesmos valores do formulário aqui. Aqui eu consigo dar um disable dynamic form.
.form.invalid. Então eu vou desabilitar enquanto tiver inválido. Pronto, tá funcionando lindo, maravilhoso! E a gente tem já o nosso formulário dinâmico aqui funcionando.
Basicamente é isso, meus amigos, dessa parte do formulário dinâmico. Agora falando para vocês desse componente em si, passando ele aqui um pouco com vocês para vocês entenderem O que que eu fiz?
Deixa eu tirar esse carinha aqui que eu não preciso, pelo visto.
Então esse componente, basicamente, quando ele é iniciado, eu crio formulário dinamicamente. Então pega minha config, e aí essa config aqui, essa model aqui, tá bom? Então eu tenho a interface no DynamicFormConfig.
Deixa eu aproveitar e mudar as nomenclaturas aqui, porque isso aqui eu criei bem no meu início, aí, Dynamic Form Config, quando eu não tinha um padrão, uma estrutura bem definida.
Mas eu vou falar com você, gente, você quer por experiência própria, 99% dos formulários que eu tenho hoje no Ministério, que são muitos, são feitos dinamicamente através dessa configuração que eu tenho aqui hoje. Então eu consigo fazer literalmente qualquer tipo de formulário aqui dentro do sistema.
Quando eu passo type aqui, ó, e o field type, eu tenho tipo de input number, select, textarea, checkbox, date, time, datetime, switch, avatar, divider.
Esse cara aqui eu posso tirar que a gente não vai utilizar.
Radio e image.
Então eu tenho literalmente todos esses tipos de input aqui no meu sistema.
Eu posso tirar esse carinha daqui e funciona, funciona muito mas muito, muito bem.
E aqui eu tenho um ngIf para cada um deles, né?
Então eu tenho um ngIf, se caso não for divider, aí eu venho aqui, se não for esses carinhas aqui, eu coloco o label para ficar no nome.
E aí vem aqui vários ngIfs, é uma forma que eu achei mais fácil porque fica tudo aqui dentro do mesmo arquivo.
Mais um ngIf para o tipo input, eu tenho tipo input number, select, tá tudo aqui.
Tudo criado através do formulário dinâmico, muito simples, muito prático e muito fácil. Então aqui do avatar, por exemplo, a gente tem um avatar aqui, a gente passa o nosso download storage, a gente vai passando tudo aqui e funciona. No final a gente tem uns erros, então eu tenho um getErrorMessage aqui, um getMessageFn, e esse carinha vai vir aqui do formErro.
Que eu tenho aqui no meu sistema.
Então se for required, ele mostra campo obrigatório. Se for email, email inválido. Valor mínimo, valor máximo, máscara para password, a senha, né, o nome obrigatório, sobrenome obrigatório, data inválida. Então eu já tenho um padrão e eu não preciso ficar adicionando isso toda hora. A única coisa que eu faço é importar e chamar esse carinha aqui e passar a minha configuração. Do autofocus. Basicamente, se tiver o autofocus, ele vai dar um autofocus nesse carinha quando ele for construído. E eu tenho minha de ícone e o pipe do download que eu já mostrei para vocês. Então basicamente é isso que a gente criou aqui.
Deixa eu atualizar também a minha tela de esqueci minha senha.
Vou fazer a mesma coisinha que eu fiz aqui, vai ser esse carinha aqui.
Password. Esse email eu vou tirar daqui.
Aqui a mesma coisa, então tinha que fazer tudo isso aqui, agora não preciso mais.
O meu componente DynamicMPDynamicFormConfig, FormConfig. E agora eu vou colocar o meu ViewChild aqui. E a mesma coisa que a gente vai continuar fazendo isso aqui. const formValue, ou eu posso só fazer dessa forma aqui mesmo. Então aqui a gente vai ter o nosso email. Agora para mim resetar esse carinha aqui, this.dynamicForm.reset. Aqui ele tá dando um erro porque quando eu for desabilitar tem que ser dynamicForm.form.reset. Valid, invalid. Perfeito, salvei. Vamos ver lá se tá funcionando. Esqueci minha senha, ele deu algum erro aqui. Perfeito, já entendi o que que é aqui.
Ele tá falando que ele não conseguiu ler a propriedade porque o Dynamic Form não tinha sido criado ainda. Uma outra possibilidade que a gente tem é fazer isso aqui, ó, password.
Vem aqui, coloca aqui. No HTML a gente tem a capacidade de fazer isso aqui. Então já tá funcionando, e a gente já tem o nosso carinha de enviar e-mail. Samuel@gmail.com. Tudo funcionando.
Cliquei para enviar, mandou o e-mail, resetou, e vai chegar na minha caixa de entrada.
Show!
Fizemos isso na página de login.
A gente vai comitar esse carinha aqui, vou dar um CCM para ir criar a mensagem de commit para mim. Ela não vai funcionar porque eu tenho— olha, funcionou! Implementing form in Rails Auth Page. Perfeito! Então aqui tá funcionando tudo certinho, fechou, comitei. E agora a gente já tem um formulário dinâmico funcionando. Aqui ele deu um erro nesse carinha aqui, porque a gente tem esse carinha aqui, ó, directive selector. Vamos mudar ele para warn. Show! Então eu só deixei ele como warn aqui e tá tudo certo.
Então nossa tela de login já tá feita e já tá com formulário dinâmico, e a gente vai para a tela de assinatura agora.
Então a gente vem aqui em app, domain, auth.
A gente tinha criado essa Sing App aqui, mas a gente não vai usar esse cara. Por quê? Vou até remover ele aqui, porque no nosso projeto a ideia não é que os usuários se cadastrem. A ideia é que o dono da barbearia, ele só pode acessar e ele pode assinar o projeto. Não vai ter um cadastro de um usuário dentro do sistema. Então a gente vai criar um módulo de subscription.
Então vai ser um módulo à parte, subscription. A gente vai criar um pages aqui. E eu vou criar o subscription page, schematic component subscription. Eu vou vir aqui mudar para CSS, mudar esse carinha aqui para page, então generate. Eu vou copiar esse cara aqui e colar aqui, subscription routes, e aqui page Subscription, subscription page, perfeito. Então já tem minha página de subscription e eu vou adicionar aqui nas rotas uma rota nova chamada subscription, vai ter esses carinhas aqui, subscription, subscription. No meu caso eu já vou chamar esse load children aqui, subscription route. Então tá feito. E quando a gente vem aqui, a gente, se a gente tentar acessar o subscription, ele tá dando um erro que eu acabei de encontrar lá relacionado no nosso Auth Service.
Então ele tá dando esse problema aqui que a gente não tem uma sessão. Se a gente não tiver uma sessão, em vez da gente deslogar o usuário e redirecionar, a gente vai só retornar, porque isso aqui é carregado bem no início. Então removi essa parte.
Se eu vier aqui Digitar subscription, subscription tá funcionando.
Então a gente vai criar agora essa parte de assinatura. Então vamos aqui no Pages e a gente vai criar um NZ Card.
A gente vai fazer a mesma coisa do Auth Layout aqui, esse mesmo carinha aqui, ó, NZ Card.
Só que aqui a gente não vai colocar título nenhum. E eu vou importar esse NZ Card, eu vou colocar o Alter Module também.
Perfeito.
No alfa layout eu também vou pegar esse carinha aqui para deixar ele centralizado.
E a gente já tem um cardizinho aqui.
E que agora a gente vai usar, achar o ng-zorro de novo, e a gente vai pegar esse carinha aqui do zorro, steps, steps. E a gente vai literalmente pegar esse carinha aqui, ó, ng-steps, aqui, aqui. E eu vou criar 3 steps. Vou deixar título nenhum, tá? Eu vou importar o NZ Steps módulo. Perfeito, a gente carrega a página de subscription e olha que legal, aqui tá no 1. Se eu coloco no 0, ele vai estar aqui no step 0. No nosso caso, a gente vai ter 2 steps apenas. Então vai ser a parte de administração e a parte de cadastro da barbearia. E agora a gente vai criar um serviço, então services, e a gente vai criar um novo serviço, subscription_service.ts. Então a gente dá um ng serve aqui, subscription_service, e a gente vai criar aqui um currentStep que vai ser um enum que a gente vai criar aqui dentro da nossa pasta enums. E a gente vem aqui e dá um new file, subscription step1.ts. É forte, é forte mesmo. Vai ser admin, vai ser o step 0, e company vai ser o step 1. A gente vai ter 2 steps, um para administrar, para os dados do administrador, né, e o outro para os dados da empresa. Então isso aqui é o primeiro passo.
Depois a gente vai criar o nosso formulário. Esse aqui a gente vai usar o formulário dinâmico, mas Para início, para esse serviço, a gente vai precisar criar um formulário, um form group novo.
Então eu vou dar um aqui, new form group, e aí aqui eu vou criar. Então aqui eu vou criar um admin, recebe um novo form group que vai ter nome, e-mail, phone e CEP. Para todos esses carinhas aqui, eu vou criar um string como NULL. E aqui o valor inicial a gente vai passar como NULL. Show! Pronto, admin e company. E aí a company a gente vai ter o nome, CNPJ e endereço. É isso aqui que a gente vai utilizar no nosso formulário. Esse vai ser o nosso formulário de assinatura. Eu vou criar um get_admin_form só para mim obter esse formulário mais rápido. E getCompanyForm também.
E eu vou criar um método submit. Esse carinha aqui a gente vai trabalhar nele ainda, mas basicamente a gente vai salvar os dados do administrador, depois salvar os dados da empresa. Então agora a gente vai criar componentes aqui dentro do nosso serviço.
Então vou criar uma pasta components e eu vou criar um componente chamado AdminDetails, que é um @MetricsComponent, admin Details CSS, e ele é um componente mesmo.
E eu vou fazer a mesma coisa para o CompanyDetails, gerar.
Perfeito.
Esses vão ser os dois formulários que a gente vai utilizar aqui dentro do nosso sistema.
Aqui a gente vai dar uma, dois detalhes do administrador. Eu vou dar um span, nz-type, É isso. Agora eu preciso começar já importar as coisas aqui, mas aqui vai ser um ztypography, module, dynamic_form_component. Vou vir a form_config aqui de uma vez.
Dynamic_form_config. Perfeito.
zdynamic_form_config, form_config. Perfeito.
E por último, um zflex.
Para a gente criar os nossos botões aqui do próximo. Dizer module small justify center. E aí eu vou criar um botão e aqui eu vou ter um router link que eu vou importar o router module e vai ser um subscription, description, barra, company, e próxima etapa. Então a gente vai ter um botãozinho aqui embaixo. Vamos ver como é que tá ficando.
Então a gente precisa agora adicionar as nossas rotas aqui dentro desse carinha.
Esse carinha aqui a gente vai criar o children path admin e loadComponent admin-details. E agora o path company, fecha aqui. E aqui vou dar um path vazio. Se ele vier vazio, vamos redirect to admin, path /full. Então se a gente volta aqui na nossa tela, olha que maravilha, ele já tá pegando essas informações aqui.
A gente vai dar uma estilizada nesse aqui primeiro, mas por enquanto ele já tá pegando.
Detalhes do administrador utilizaremos abaixo no sistema. Então a gente vai vir aqui, a gente vai importar um button module dentro do sistema. Tema aqui para ele pegar o próximo etapa bonitinho.
Vamos criar o nosso form config agora. E esse carinha aqui, ele vai ter aquele, aqueles dados do subscription service. Então, para ser mais rápido, eu vou ajudar o Copilot a criar esses carrinhos para mim.
Coloquei aqui em cima, só que o Copilot normalmente ele não lembra. Praticamente ele criou aqui tudo junto. E-mail, o telefone a gente vai botar a máscara. Então a gente tem aqui 1234 ou telefone fixo 00. E aqui o type field, tel, tel, tel.
Oh, já tá gerando tudo aqui.
Então já tem o nome, Email, telefone, já tá com a minha máscara, a senha, o email, já tá tudo funcionando aqui. Então vamos dar uma estilizada aqui, vamos fazer isso aqui dentro do subscription page, que aí eu acho mais fácil. ngZip, -2, text-align: center.
Vamos ver, pegou aqui, ó, já instalou.
ngSteps, width: 80%, text-align: center. Beleza, só para ele não ficar cá nas pontinhas. Esse carinha, margin, bota um rem. E aqui, meu, perfeito. Então a gente já tem os nossos dados do administrador. Deixa eu dar um F5 aqui na página.
Temos o nosso detalhes do administrador, utilizaremos os dados abaixo para criar sua conta no sistema.
E aí que quando a gente criar nossa próxima etapa aqui, a gente for para o próximo A gente tem que trabalhar nessa parte aqui agora.
Aí aqui nesse card aqui a gente precisa mexer de uma forma que vai ficar subscription.
Perfeito. Company details, works. Mesma coisa para o company details, que é detalhes da empresa.
Importante, tudo.
Perfeito, essa parte aqui tá ok também. Teste, aceita os números e o meu endereço tá aqui. Etapa anterior de criar conta, eu vou colocar um ícone Nesses carinhas aqui e nesse icon left.
Deixa eu ver se eu já tô importando esse icon, provavelmente não.
NZ Icon Model.
Vou importar esse cara aqui também. Porque no próximo então, tá? Correto. Mesma coisa aqui. Deixa eu aí, deixa esse cara aqui em outro modo.
Perfeito.
Etapa anterior.
E criar conta.
Só que esse aqui não vai ser assim, vou colocar um erro left, erro right, e aqui vai ser um erro também, vai ficar mais bonitinho, né? Então, perfeito.
Então, etapa anterior, próxima etapa, e depois aqui criar conta, ele já vai pegar todos os meus dados do meu formulário que eu tô preenchendo.
Aqui tem que pôr um text-center, que eu quero que o texto fique centralizado.
Exato, perfeito.
Então, bastante coisa aqui, mas eu quero ainda deixar um bolo da cereja para vocês aqui, para a gente criar essa parte de endereço.
Então, próximo vídeo a gente vai criar toda a parte da conta no sistema, mas hoje a gente vai finalizar essa parte aqui criando esse formulário, porque o vídeo já tá bem longo, mas eu quero deixar um bolo na cereja aqui para vocês com a parte do endereço.
Então, no endereço a gente não vai ter um address, a gente vai ter um zip code, a gente vai ter um address, agora endereço, número, complemento, bairro, cidade, estado e país, country. A gente vai ter tudo isso aqui no nosso formulário, tá bom?
E a gente vai criar isso dinamicamente aqui no nosso company details. Então, em vez de ter só um campo de endereço, eu vou pegar aqui no meu SaaS, como que eu pego essa parte de CEP? E eu vou colar aqui para mostrar para vocês essa maravilha aqui.
Então, primeira coisa que eu preciso dar um npm install cep-prompts, esse carinha aqui do CEP Prompts.
Mas basicamente eu tenho um CEP Eu vou precisar transformar isso aqui em uma função, só que para isso eu não gosto de deixar esse carinha aqui.
Então eu vou criar um constante e eu vou criar um form config. É esse, form config. Exato, esse carinha aqui mesmo. Nesse caso aqui eu preciso criar uma função, vocês vão entender.
Ok, return.
E aí eu vou pegar esse carinha aqui todo colar aqui, importar todo mundo. Beleza. E aí agora eu vou criar umas funções aqui, ó, const enableFields, e aqui a mesma coisa para o disableFields. Escanecam o form group, vocês vão ver a mágica acontecendo aqui no sistema. Eu tenho essa UFList aqui E eu vou só colocar ela aqui, só uma constante com todas as cidades do Brasil.
E bom, basicamente, olha o que que vai acontecer. Eu tô falando que eu tenho um cara do CEP aqui, e quando ele digitar o CEP, quando ele terminar, eu vou verificar se ele tá inválido. Se tiver inválido, eu retorno, mas se não, eu vou chamar o CEP Promise passando o zip code. E eu vou preencher o meu formulário com os valores exatos aqui, ó, do cara, e vou desabilitar os meus campos. Se der um erro, eu removo os valores e habilito os meus campos, todos esses campos que estão aqui embaixo aqui, ó. Então vocês vão ver agora, meus amigos, essa mágica acontecendo.
Então, que vai ser esse carinha aqui, Company Form Config.
Salvei.
Beleza, tá funcionando. E olha a maravilha que é isso aqui. Eu acho que esse carinha tá assim porque eu tô, eu coloquei esse text-align aqui no card. Isso mesmo.
Bom, então agora vamos ver a mágica acontecendo.
Então a gente tem o CEP aqui funcionando e eu vou colocar um CEP. E pronto, meus amigos, olha a mágica feita.
Botei o CEP E ele já preencheu automaticamente a rua, bairro, cidade, estado, país. E aí falta só colocar o número, colocar 123 aqui, por exemplo. Então a gente já tem uma parte de CEP com autocomplete funcionando no formulário dinâmico, com as etapas de anterior e próxima etapa. E agora mais um detalhe, um pulo do gato aqui para vocês. Pra ficar mais fácil ainda, porque quando a gente está atualizando a nossa página, a gente está perdendo o valor. Então o que eu vou fazer?
Eu vou vir aqui no meu shared widget directives e eu vou chamar esse FormStorageDirective aqui. Isso aqui é uma maravilha, gente. Deixa eu mudar pra mbFormStorage. mbFormStorage. Então, beleza. Aqui ele tá falando que não aceita nulo. Pronto.
Então, o que que essa diretiva vai fazer? Quando eu iniciar ela, quando eu importar ela em alguma página, o que que ela vai fazer? Ela vai criar um FormGroup, ela vai no ng-on-init atualizar os valores do localStorage e vai dar um listenAndUpdate. Para quê? Para que quando tiver alguma alteração, ele salvar isso automaticamente no localStorage. Então, meus amigos, a única coisa que eu preciso fazer para ter um gerenciamento de estado da minha aplicação é importar essa diretiva aqui.
Então é pegar esse carinha aqui e aqui, lembra que a gente criou aqui no nosso service esse form?
Então agora a gente vai utilizar esse carinha.
Então aqui eu vou dar um um form, FormGroup, RecebProtectedSubscriptionService, SubscriptionService.form, mdbFormStorage. Deixa eu só importar o React aqui, React Forms Module. Então, mdb form_store_subscription_form.
Então a gente criou essa parte aqui. Agora nós nos componentes a gente tem que dar um after_view_init.
this.dynamic_form_child, dynamic_form_value_change.pipe.to_destroy this debounceTime 300. Eu não vou salvar esse carinha aqui porque agora eu vou importar o meu SubscriptionService aqui. Aqui eu vou minimizar, aqui eu dou um private const formReceive getAdminForm, getValue, implements AfterViewInit. Perfeito. A mesma coisa para o meu CompanyDetails aqui, ó. Mesma coisa, mesma coisa, mesma coisa. A mesma coisa aqui. Agora vamos ver se ele tá chegando aqui. Aqui, tô longe de mim.
Samuel, beleza.
Vamos ver aqui no nosso application. E olha a maravilha! Olha isso aqui, gente, olha isso aqui. SamuelRizon10@gmail.com. Ele já tá atualizando.
Se eu recarrego a página, ele não tá pegando porque eu não atualizei o meu carinha.
Então eu venho aqui, this.dynamic_form.form.getvalue, get_admin_form. Exatamente isso aqui, primeira coisa aqui. Agora aqui a mesma coisa, só que aqui é get_company_form. Quando eu atualizar, tá feito, meus amigos.
Então agora o nosso formulário tá salvando as informações no local storage.
E quando eu venho aqui, Samuel, ison, s@s.com, telefone 123456.
Se eu vou para a próxima etapa, nome da empresa Barbearia, CNPJ, CEP, e tudo aqui, um número, 123, recarrego a página. Galera, não tá salvando aqui.
E eu já sei por quê. Quando a gente vem aqui no nosso carinha, eu tô dando um.value, só que os outros campos estão desabilitados.
Então, meus amigos, a gente não pode dar um.value aqui, a gente tem que dar um getRawValue.
Então provavelmente isso aqui é o fato dele não tá sendo preenchido. Então eu salvo esse carinha aqui. Ainda não tá, ainda não tá funcionando. Se eu der um status change aqui, então, this.dynamic_form.get_row_value, esse cara eu tiro ele daqui. Agora a gente vai ter o nosso formulário com o valor correto, 45. E quando a gente vem aqui, tá tudo preenchido. Dá um F5, tá tudo funcionando.
Então é isso, meus amigos, já tem muito tempo de vídeo, a gente fez bastante coisa aqui e eu vou deixar a próxima etapa para o próximo vídeo. Se você gostou desse vídeo, se inscreve no canal, deixa o joinha e até a próxima. Valeu!










