diff --git a/aio/content/examples/reactive-forms/debug.log b/aio/content/examples/reactive-forms/debug.log deleted file mode 100644 index 9c0793f598..0000000000 --- a/aio/content/examples/reactive-forms/debug.log +++ /dev/null @@ -1,3 +0,0 @@ -[1030/162525.401:ERROR:process_reader_win.cc(123)] NtOpenThread: {Acceso denegado} Un proceso ha solicitado acceso a un objeto, pero no se le han concedido esos derechos de acceso. (0xc0000022) -[1030/162525.402:ERROR:exception_snapshot_win.cc(87)] thread ID 26896 not found in process -[1030/162525.402:WARNING:crash_report_exception_handler.cc(62)] ProcessSnapshotWin::Initialize failed diff --git a/aio/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts b/aio/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts index 59c1ea797d..25022d2290 100644 --- a/aio/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts +++ b/aio/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts @@ -2,1019 +2,144 @@ import { browser, element, by } from 'protractor'; -function finalDemoAddressForm(element: any, index: number) { - let form = { - street: element.all(by.css('input[formcontrolname=street]')).get(index).getAttribute('value'), - city: element.all(by.css('input[formcontrolname=city]')).get(index).getAttribute('value'), - state: element.all(by.css('select[formcontrolname=state]')).get(index).getAttribute('value'), - zip: element.all(by.css('input[formcontrolname=zip]')).get(index).getAttribute('value') - }; - return form; -} +describe('Reactive forms', function () { + const nameEditor = element(by.css('app-name-editor')); + const profileEditor = element(by.css('app-profile-editor')); + const nameEditorLink = element(by.cssContainingText('app-root > nav > a', 'Name Editor')); + const profileEditorLink = element(by.cssContainingText('app-root > nav > a', 'Profile Editor')); -describe('Reactive forms', function() { - let select: any; - - beforeEach(function() { + beforeAll(function () { browser.get(''); - select = element(by.css('.container > h4 > select')); }); - describe('navigation', function() { - it('should display the title', function() { - let title = element(by.css('.container > h1')); - expect(title.getText()).toBe('Reactive Forms'); + describe('Name Editor', function () { + const nameInput = nameEditor.element(by.css('input')); + const updateButton = nameEditor.element(by.buttonText('Update Name')); + const nameText = 'John Smith'; + + beforeAll(async () => { + await nameEditorLink.click(); }); - it('should contain a dropdown with each example', function() { - expect(select.isDisplayed()).toBe(true); + beforeEach(async () => { + await nameInput.clear(); }); - it('should have 9 options for different demos', function() { - let options = select.all(by.tagName('option')); - expect(options.count()).toBe(9); + it('should update the name value when the name control is updated', async () => { + await nameInput.sendKeys(nameText); + + const value = await nameInput.getAttribute('value'); + + expect(value).toBe(nameText); }); - it('should start with Final Demo', function() { - select.getAttribute('value').then(function(demo: string) { - expect(demo).toBe('Final Demo'); - }); + it('should update the name control when the Update Name button is clicked', async () => { + await nameInput.sendKeys(nameText); + const value = await nameInput.getAttribute('value'); + + expect(value).toBe(nameText); + await updateButton.click(); + + const value = await nameInput.getAttribute('value'); + + expect(value).toBe('Nancy'); + }); + + it('should update the displayed control value when the name control updated', async () => { + await nameInput.sendKeys(nameText); + const valueElement = nameEditor.element(by.cssContainingText('p', 'Value:')); + const nameValueElement = await valueElement.getText(); + const nameValue = nameValueElement.toString().replace('Value: ', ''); + + expect(nameValue).toBe(nameText); }); }); -// *************Begin Final Demo test******************************* + describe('Profile Editor', function () { + const firstNameInput = getInput('firstName'); + const lastNameInput = getInput('lastName'); + const streetInput = getInput('street'); + const addAliasButton = element(by.buttonText('Add Alias')); + const updateButton = profileEditor.element(by.buttonText('Update Profile')); + const profile = { + firstName: 'John', + lastName: 'Smith', + street: '345 South Lane', + city: 'Northtown', + state: 'XX', + zip: 12345 + }; - describe('final demo', function() { - it('does not select any hero by default', function() { - let heroSection = element(by.css('app-hero-list > div')); - expect(heroSection.isPresent()).toBe(false); + beforeAll(async () => { + await profileEditorLink.click(); }); - it('refreshes the page upon button click', function() { - // We move to another page... - let whirlwindButton = element.all(by.css('nav a')).get(0); - whirlwindButton.click(); - let refresh = element(by.css('button')); - refresh.click(); - let heroSection = element(by.css('app-hero-list > div')); - expect(heroSection.isPresent()).toBe(false); + beforeEach(async () => { + await browser.get(''); + await profileEditorLink.click(); }); - describe('Whirlwind form', function() { - beforeEach(function() { - let whirlwindButton = element.all(by.css('nav a')).get(0); - whirlwindButton.click(); - }); - - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('app-hero-list > div > h3')); - expect(editMessage.getText()).toBe('Editing: Whirlwind'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Whirlwind'); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe('123 Main'); - expect(address1.state).toBe('CA'); - expect(address1.zip).toBe('94801'); - expect(address1.city).toBe('Anywhere'); - let address2 = finalDemoAddressForm(element, 1); - expect(address2.street).toBe('456 Maple'); - expect(address2.state).toBe('VA'); - expect(address2.zip).toBe('23226'); - expect(address2.city).toBe('Somewhere'); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail > p')); - expect(json.getText()).toContain('Whirlwind'); - expect(json.getText()).toContain('Anywhere'); - expect(json.getText()).toContain('Somewhere'); - expect(json.getText()).toContain('VA'); - }); - - it('has two disabled buttons by default', function() { - let buttons = element.all(by.css('app-hero-detail > form > div > button')); - expect(buttons.get(0).getAttribute('disabled')).toBe('true'); - expect(buttons.get(1).getAttribute('disabled')).toBe('true'); - }); - - it('enables the buttons after we edit the form', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - nameInput.sendKeys('a'); - let buttons = element.all(by.css('app-hero-detail > form > div > button')); - expect(buttons.get(0).getAttribute('disabled')).toBeNull(); - expect(buttons.get(1).getAttribute('disabled')).toBeNull(); - }); - - it('saves the changes when the save button is clicked', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - nameInput.sendKeys('a'); - let save = element.all(by.css('app-hero-detail > form > div > button')).get(0); - save.click(); - let editMessage = element(by.css('app-hero-list > div > h3')); - expect(editMessage.getText()).toBe('Editing: Whirlwinda'); - }); - - it('reverts the changes when the revert button is clicked', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - nameInput.sendKeys('a'); - let revert = element.all(by.css('app-hero-detail > form > div > button')).get(1); - revert.click(); - let editMessage = element(by.css('app-hero-list > div > h3')); - expect(editMessage.getText()).toBe('Editing: Whirlwind'); - expect(nameInput.getAttribute('value')).toBe('Whirlwind'); - }); - - it('is able to add a new empty address', function() { - let newLairButton = element.all(by.css('button')).get(3); - newLairButton.click(); - let address3 = finalDemoAddressForm(element, 2); - expect(address3.street).toBe(''); - expect(address3.state).toBe(''); - expect(address3.zip).toBe(''); - expect(address3.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); + it('should be invalid by default', async () => { + expect(await profileEditor.getText()).toContain('Form Status: INVALID'); }); - describe('Bombastic form', function() { - beforeEach(function() { - let bombastaButton = element.all(by.css('nav a')).get(1); - bombastaButton.click(); - }); + it('should be valid if the First Name is filled in', async () => { + await firstNameInput.clear(); + await firstNameInput.sendKeys('John Smith'); - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('app-hero-list > div > h3')); - expect(editMessage.getText()).toBe('Editing: Bombastic'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Bombastic'); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe('789 Elm'); - // expect(address1.state).toBe('OH'); - expect(address1.zip).toBe('04501'); - expect(address1.city).toBe('Smallville'); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail > p')); - expect(json.getText()).toContain('Bombastic'); - expect(json.getText()).toContain('Smallville'); - expect(json.getText()).toContain('OH'); - expect(json.getText()).toContain('04501'); - }); - - it('has two disabled buttons by default', function() { - let buttons = element.all(by.css('app-hero-detail > form > div > button')); - expect(buttons.get(0).getAttribute('disabled')).toBe('true'); - expect(buttons.get(1).getAttribute('disabled')).toBe('true'); - }); - - it('enables the buttons after we edit the form', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - nameInput.sendKeys('a'); - let buttons = element.all(by.css('app-hero-detail > form > div > button')); - expect(buttons.get(0).getAttribute('disabled')).toBeNull(); - expect(buttons.get(1).getAttribute('disabled')).toBeNull(); - }); - - it('saves the changes when the save button is clicked', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - nameInput.sendKeys('a'); - let save = element.all(by.css('app-hero-detail > form > div > button')).get(0); - save.click(); - let editMessage = element(by.css('app-hero-list > div > h3')); - expect(editMessage.getText()).toBe('Editing: Bombastica'); - }); - - it('reverts the changes when the revert button is clicked', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - nameInput.sendKeys('a'); - let revert = element.all(by.css('app-hero-detail > form > div > button')).get(1); - revert.click(); - let editMessage = element(by.css('app-hero-list > div > h3')); - expect(editMessage.getText()).toBe('Editing: Bombastic'); - expect(nameInput.getAttribute('value')).toBe('Bombastic'); - }); - - it('is able to add a new empty address', function() { - let newLairButton = element.all(by.css('button')).get(3); - newLairButton.click(); - let address2 = finalDemoAddressForm(element, 1); - expect(address2.street).toBe(''); - expect(address2.state).toBe(''); - expect(address2.zip).toBe(''); - expect(address2.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); + expect(await profileEditor.getText()).toContain('Form Status: VALID'); }); - describe('Magneta form', function() { + it('should update the name when the button is clicked', async () => { + await firstNameInput.clear(); + await streetInput.clear(); + await firstNameInput.sendKeys('John'); + await streetInput.sendKeys('345 Smith Lane'); + const firstNameInitial = await firstNameInput.getAttribute('value'); + const streetNameInitial = await streetInput.getAttribute('value'); - beforeEach(function() { - let magnetaButton = element.all(by.css('nav a')).get(2); - magnetaButton.click(); - }); + expect(firstNameInitial).toBe('John'); + expect(streetNameInitial).toBe('345 Smith Lane'); + await updateButton.click(); - it('should show hero information when the button is clicked', function() { - let editMessage = element(by.css('app-hero-list > div > h3')); - expect(editMessage.getText()).toBe('Editing: Magneta'); - }); + const nameValue = await firstNameInput.getAttribute('value'); + const streetValue = await streetInput.getAttribute('value'); - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Magneta'); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail > p')); - expect(json.getText()).toContain('Magneta'); - }); - - it('has two disabled buttons by default', function() { - let buttons = element.all(by.css('app-hero-detail > form > div > button')); - expect(buttons.get(0).getAttribute('disabled')).toBe('true'); - expect(buttons.get(1).getAttribute('disabled')).toBe('true'); - }); - - it('enables the buttons after we edit the form', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - nameInput.sendKeys('a'); - let buttons = element.all(by.css('app-hero-detail > form > div > button')); - expect(buttons.get(0).getAttribute('disabled')).toBeNull(); - expect(buttons.get(1).getAttribute('disabled')).toBeNull(); - }); - - it('saves the changes when the save button is clicked', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - nameInput.sendKeys('a'); - let save = element.all(by.css('app-hero-detail > form > div > button')).get(0); - save.click(); - let editMessage = element(by.css('app-hero-list > div > h3')); - expect(editMessage.getText()).toBe('Editing: Magnetaa'); - }); - - it('reverts the changes when the revert button is clicked', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - nameInput.sendKeys('a'); - let revert = element.all(by.css('app-hero-detail > form > div > button')).get(1); - revert.click(); - let editMessage = element(by.css('app-hero-list > div > h3')); - expect(editMessage.getText()).toBe('Editing: Magneta'); - expect(nameInput.getAttribute('value')).toBe('Magneta'); - }); - - it('is able to add a new empty address', function() { - let newLairButton = element.all(by.css('button')).get(3); - newLairButton.click(); - let address = finalDemoAddressForm(element, 0); - expect(address.street).toBe(''); - expect(address.state).toBe(''); - expect(address.zip).toBe(''); - expect(address.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - }); - }); // final demo - -// *************Begin FormArray Demo test******************************* - - - describe('formArray demo', function() { - beforeEach(function() { - let FormArrayOption = element.all(by.css('select option')).get(7); - FormArrayOption.click(); + expect(nameValue).toBe('Nancy'); + expect(streetValue).toBe('123 Drew Street'); }); - it('should show FormArray Demo', function() { - select.getAttribute('value').then(function(demo: string) { - expect(demo).toBe('FormArray Demo'); - }); - }); + it('should add an alias field when the Add Alias button is clicked', async () => { + await addAliasButton.click(); - it('does not select any hero by default', function() { - let heroSection = element(by.css('app-hero-list > div')); - expect(heroSection.isPresent()).toBe(false); + const aliasInputs = profileEditor.all(by.cssContainingText('label', 'Alias')); + + expect(await aliasInputs.count()).toBe(2); }); - it('refreshes the page upon button click', function() { - // We move to another page... - let whirlwindButton = element.all(by.css('nav a')).get(0); - whirlwindButton.click(); - let refresh = element(by.css('button')); - refresh.click(); - let heroSection = element(by.css('app-hero-list > div')); - expect(heroSection.isPresent()).toBe(false); + it('should update the displayed form value when form inputs are updated', async () => { + const aliasText = 'Johnny'; + const inputs = await Promise.all( + Object.keys(profile) + .map(key => + getInput(key).sendKeys(`${profile[key]}`) + ) + ); + + const aliasInputs = profileEditor.all(by.cssContainingText('label', 'Alias')); + const aliasInput = aliasInputs.get(0).element(by.css('input')); + await aliasInput.sendKeys(aliasText); + const formValueElement = profileEditor.all(by.cssContainingText('p', 'Form Value:')); + const formValue = await formValueElement.getText(); + const formJson = JSON.parse(formValue.toString().replace('Form Value:', '')); + + expect(profile.firstName).toBe(formJson.firstName); + expect(profile.lastName).toBe(formJson.lastName); + expect(formJson.aliases[0]).toBe(aliasText); }); + }); - describe('Whirlwind form', function() { - beforeEach(function() { - let whirlwindButton = element.all(by.css('nav a')).get(0); - whirlwindButton.click(); - }); - - it('should show hero information when the button is clicked', function() { - let editMessage = element(by.css('div.demo > div > div > h3')); - expect(editMessage.getText()).toBe('Editing: Whirlwind'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Whirlwind'); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe('123 Main'); - expect(address1.state).toBe('CA'); - expect(address1.zip).toBe('94801'); - expect(address1.city).toBe('Anywhere'); - let address2 = finalDemoAddressForm(element, 1); - expect(address2.street).toBe('456 Maple'); - expect(address2.state).toBe('VA'); - expect(address2.zip).toBe('23226'); - expect(address2.city).toBe('Somewhere'); - }); - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-8 > p')); - expect(json.getText()).toContain('Whirlwind'); - expect(json.getText()).toContain('Anywhere'); - expect(json.getText()).toContain('Somewhere'); - expect(json.getText()).toContain('VA'); - }); - - it('is able to add a new empty address', function() { - let newLairButton = element.all(by.css('button')).get(1); - newLairButton.click(); - let address2 = finalDemoAddressForm(element, 2); - expect(address2.street).toBe(''); - expect(address2.state).toBe(''); - expect(address2.zip).toBe(''); - expect(address2.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - }); // Whirlwind form - - describe('Bombastic FormArray form', function() { - beforeEach(function() { - let bombasticButton = element.all(by.css('nav a')).get(1); - bombasticButton.click(); - }); - - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('div.demo > div > div > h3')); - expect(editMessage.getText()).toBe('Editing: Bombastic'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - // nameInput.getAttribute('value').then(function(name: string) { - // expect(name).toBe('Whirlwind'); - // }); - expect(nameInput.getAttribute('value')).toBe('Bombastic'); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe('789 Elm'); - // expect(address1.state).toBe('OH'); - // This select should be OH not CA, which it shows in the UI, the JSON shows OH. - expect(address1.zip).toBe('04501'); - expect(address1.city).toBe('Smallville'); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-8 > p')); - expect(json.getText()).toContain('Bombastic'); - expect(json.getText()).toContain('Smallville'); - expect(json.getText()).toContain('04501'); - expect(json.getText()).toContain('789 Elm'); - }); - - it('is able to add a new empty address', function() { - let newLairButton = element.all(by.css('button')).get(1); - newLairButton.click(); - let address1 = finalDemoAddressForm(element, 1); - expect(address1.street).toBe(''); - expect(address1.state).toBe(''); - expect(address1.zip).toBe(''); - expect(address1.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - }); // Bombastic FormArray form - - describe('Magneta FormArray form', function() { - beforeEach(function() { - let magnetaButton = element.all(by.css('nav a')).get(2); - magnetaButton.click(); - }); - - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('div.demo > div > div > h3')); - expect(editMessage.getText()).toBe('Editing: Magneta'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Magneta'); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-8 > p')); - expect(json.getText()).toContain('Magneta'); - }); - - it('is able to add a new empty address', function() { - let newLairButton = element.all(by.css('button')).get(1); - newLairButton.click(); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe(''); - expect(address1.state).toBe(''); - expect(address1.zip).toBe(''); - expect(address1.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - }); // Magneta FormArray form - - }); // formArray demo - - -// *************Begin SetValue Demo test******************************* - - describe('SetValue demo', function() { - beforeEach(function() { - let SetValueOption = element.all(by.css('select option')).get(6); - SetValueOption.click(); - }); - - it('should show SetValue Demo', function() { - select.getAttribute('value').then(function(demo: string) { - expect(demo).toBe('SetValue Demo'); - }); - }); - - it('does not select any hero by default', function() { - let heroSection = element(by.css('app-hero-list > div')); - expect(heroSection.isPresent()).toBe(false); - }); - - it('refreshes the page upon button click', function() { - // We move to another page... - let whirlwindButton = element.all(by.css('nav a')).get(0); - whirlwindButton.click(); - let refresh = element(by.css('button')); - refresh.click(); - let heroSection = element(by.css('app-hero-list > div')); - expect(heroSection.isPresent()).toBe(false); - }); - - describe('Whirlwind setValue form', function() { - beforeEach(function() { - let whirlwindButton = element.all(by.css('nav a')).get(0); - whirlwindButton.click(); - }); - - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('.demo > div > div > h3')); - expect(editMessage.getText()).toBe('Editing: Whirlwind'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Whirlwind'); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe('123 Main'); - expect(address1.state).toBe('CA'); - expect(address1.zip).toBe('94801'); - expect(address1.city).toBe('Anywhere'); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-7 > p')); - expect(json.getText()).toContain('Whirlwind'); - expect(json.getText()).toContain('Anywhere'); - let nameOutput = element(by.css('app-hero-detail-7 > p ~ p')); - expect(nameOutput.getText()).toContain('Name value: Whirlwind'); - let streetOutput = element(by.css('app-hero-detail-7 > p ~ p ~ p')); - expect(streetOutput.getText()).toContain('Street value: 123 Main'); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - }); // Whirlwind setValue form - - describe('Bombastic setValue form', function() { - beforeEach(function() { - let bombasticButton = element.all(by.css('nav a')).get(1); - bombasticButton.click(); - }); - - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('.demo > div > div > h3')); - expect(editMessage.getText()).toBe('Editing: Bombastic'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Bombastic'); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe('789 Elm'); - expect(address1.state).toBe('OH'); - expect(address1.zip).toBe('04501'); - expect(address1.city).toBe('Smallville'); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-7 > p')); - expect(json.getText()).toContain('Bombastic'); - expect(json.getText()).toContain('Smallville'); - expect(json.getText()).toContain('04501'); - expect(json.getText()).toContain('789 Elm'); - let nameOutput = element(by.css('app-hero-detail-7 > p ~ p')); - expect(nameOutput.getText()).toContain('Name value: Bombastic'); - let streetOutput = element(by.css('app-hero-detail-7 > p ~ p ~ p')); - expect(streetOutput.getText()).toContain('Street value: 789 Elm'); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - }); // Bombastic setValue form - - describe('Magneta setValue form', function() { - beforeEach(function() { - let magnetaButton = element.all(by.css('nav a')).get(2); - magnetaButton.click(); - }); - - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('.demo > div > div > h3')); - expect(editMessage.getText()).toBe('Editing: Magneta'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Magneta'); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-7 > p')); - expect(json.getText()).toContain('Magneta'); - let nameOutput = element(by.css('app-hero-detail-7 > p ~ p')); - expect(nameOutput.getText()).toContain('Name value: Magneta'); - let streetOutput = element(by.css('app-hero-detail-7 > p ~ p ~ p')); - expect(streetOutput.getText()).toContain('Street value:'); - }); - - }); // Magneta setValue form - }); // SetValue demo - -// *************Begin patchValue Demo test******************************* - - describe('patchValue demo', function() { - beforeEach(function() { - let SetValueOption = element.all(by.css('select option')).get(5); - SetValueOption.click(); - }); - - it('should show patchValue Demo', function() { - select.getAttribute('value').then(function(demo: string) { - expect(demo).toBe('PatchValue Demo'); - }); - }); - - it('does not select any hero by default', function() { - let heroSection = element(by.css('.demo > div > div')); - expect(heroSection.isPresent()).toBe(false); - }); - - it('refreshes the page upon button click', function() { - // We move to another page... - let whirlwindButton = element.all(by.css('nav a')).get(0); - whirlwindButton.click(); - let refresh = element(by.css('button')); - refresh.click(); - let heroSection = element(by.css('.demo > div > div')); - expect(heroSection.isPresent()).toBe(false); - }); - - describe('Whirlwind patchValue form', function() { - beforeEach(function() { - let whirlwindButton = element.all(by.css('nav a')).get(0); - whirlwindButton.click(); - }); - - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('h2 ~ h3')); - expect(editMessage.getText()).toBe('Editing: Whirlwind'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Whirlwind'); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe(''); - expect(address1.state).toBe(''); - expect(address1.zip).toBe(''); - expect(address1.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-6 > p')); - expect(json.getText()).toContain('Whirlwind'); - let nameOutput = element(by.css('app-hero-detail-6 > p ~ p')); - expect(nameOutput.getText()).toContain('Name value: Whirlwind'); - let streetOutput = element(by.css('app-hero-detail-6 > p ~ p ~ p')); - expect(streetOutput.getText()).toContain('Street value:'); - }); - - - }); // Bombastic patchValue form - describe('Bombastic patchValue form', function() { - beforeEach(function() { - let bombasticButton = element.all(by.css('nav a')).get(1); - bombasticButton.click(); - }); - - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('h2 ~ h3')); - expect(editMessage.getText()).toBe('Editing: Bombastic'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Bombastic'); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe(''); - expect(address1.state).toBe(''); - expect(address1.zip).toBe(''); - expect(address1.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-6 > p')); - expect(json.getText()).toContain('Bombastic'); - let nameOutput = element(by.css('app-hero-detail-6 > p ~ p')); - expect(nameOutput.getText()).toContain('Name value: Bombastic'); - let streetOutput = element(by.css('app-hero-detail-6 > p ~ p ~ p')); - expect(streetOutput.getText()).toContain('Street value:'); - }); - }); // Bombastic patchValue form - - describe('Magneta patchValue form', function() { - beforeEach(function() { - let magnetaButton = element.all(by.css('nav a')).get(2); - magnetaButton.click(); - }); - - it('should show a hero information when the button is clicked', function() { - let editMessage = element(by.css('h2 ~ h3')); - expect(editMessage.getText()).toBe('Editing: Magneta'); - }); - - it('should show a form with the selected hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe('Magneta'); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe(''); - expect(address1.state).toBe(''); - expect(address1.zip).toBe(''); - expect(address1.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-6 > p')); - expect(json.getText()).toContain('Magneta'); - let nameOutput = element(by.css('app-hero-detail-6 > p ~ p')); - expect(nameOutput.getText()).toContain('Name value: Magneta'); - let streetOutput = element(by.css('app-hero-detail-6 > p ~ p ~ p')); - expect(streetOutput.getText()).toContain('Street value:'); - }); - - }); // Magneta patchValue form - }); // PatchValue demo - - - -// *************Begin Nested FormBuilder Demo test******************************* - - describe('Nested FormBuilder demo', function() { - beforeEach(function() { - let NestedFormBuilderOption = element.all(by.css('select option')).get(4); - NestedFormBuilderOption.click(); - }); - - it('should show Nested FormBuilder Demo', function() { - select.getAttribute('value').then(function(demo: string) { - expect(demo).toBe('Nested FormBuilder group Demo'); - }); - }); - - it('should show a form for hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe(''); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe(''); - expect(address1.state).toBe(''); - expect(address1.zip).toBe(''); - expect(address1.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-5 > p')); - expect(json.getText()).toContain('address'); - let nameOutput = element(by.css('app-hero-detail-5 > p ~ p')); - expect(nameOutput.getText()).toContain('Name value:'); - let streetOutput = element(by.css('app-hero-detail-5 > p ~ p ~ p')); - expect(streetOutput.getText()).toContain('Street value:'); - }); - - }); // Nested FormBuilder demo - -// *************Begin Group with multiple controls Demo test******************************* - - describe('Group with multiple controls demo', function() { - beforeEach(function() { - let NestedFormBuilderOption = element.all(by.css('select option')).get(3); - NestedFormBuilderOption.click(); - }); - - it('should show Group with multiple controls Demo', function() { - select.getAttribute('value').then(function(demo: string) { - expect(demo).toBe('Group with multiple controls Demo'); - }); - }); - - it('should show header', function() { - let header = element(by.css('app-hero-detail-4 > h3')); - expect(header.getText()).toBe('A FormGroup with multiple FormControls'); - }); - - it('should show a form for hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe(''); - let address1 = finalDemoAddressForm(element, 0); - expect(address1.street).toBe(''); - expect(address1.state).toBe(''); - expect(address1.zip).toBe(''); - expect(address1.city).toBe(''); - }); - - it('should show three radio buttons', function() { - let radioButtons = element.all(by.css('input[formcontrolname=power]')); - expect(radioButtons.get(0).getAttribute('value')).toBe('flight'); - expect(radioButtons.get(1).getAttribute('value')).toBe('x-ray vision'); - expect(radioButtons.get(2).getAttribute('value')).toBe('strength'); - }); - it('should show a checkbox', function() { - let checkbox = element(by.css('input[formcontrolname=sidekick]')); - expect(checkbox.getAttribute('checked')).toBe(null); - }); - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-4 > p')); - expect(json.getText()).toContain('power'); - }); - -}); // Group with multiple controls demo - - - -// *************Begin Group with multiple controls Demo test******************************* - - describe('Simple FormBuilder Group demo', function() { - beforeEach(function() { - let SimpleFormBuilderOption = element.all(by.css('select option')).get(2); - SimpleFormBuilderOption.click(); - }); - - it('should show Simple FormBuilder group Demo', function() { - select.getAttribute('value').then(function(demo: string) { - expect(demo).toBe('Simple FormBuilder group Demo'); - }); - }); - - it('should show header', function() { - let header = element(by.css('app-hero-detail-3 > h3')); - expect(header.getText()).toBe('A FormGroup with a single FormControl using FormBuilder'); - }); - - it('should show a form for hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe(''); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-3 > p')); - expect(json.getText()).toContain('name'); - let validStatus = element(by.css('app-hero-detail-3 > p ~ p')); - expect(validStatus.getText()).toContain('INVALID'); - }); - -}); // Group with multiple controls demo - - -// *************Begin FormControl in a FormGroup Demo test******************************* - - describe('FormControl in a FormGroup demo', function() { - beforeEach(function() { - let SimpleFormBuilderOption = element.all(by.css('select option')).get(1); - SimpleFormBuilderOption.click(); - }); - - it('should show FormControl in a FormGroup Demo', function() { - select.getAttribute('value').then(function(demo: string) { - expect(demo).toBe('FormControl in a FormGroup Demo'); - }); - }); - - it('should show header', function() { - let header = element(by.css('app-hero-detail-2 > h3')); - expect(header.getText()).toBe('FormControl in a FormGroup'); - }); - - it('should show a form for hero information', function() { - let nameInput = element(by.css('input[formcontrolname=name]')); - expect(nameInput.getAttribute('value')).toBe(''); - }); - - it('shows a json output from the form', function() { - let json = element(by.css('app-hero-detail-2 > p')); - expect(json.getText()).toContain('name'); - }); - -}); // Group with multiple controls demo - -// *************Begin Just A FormControl Demo test******************************* - - describe('Just a FormControl demo', function() { - beforeEach(function() { - let FormControlOption = element.all(by.css('select option')).get(0); - FormControlOption.click(); - }); - - it('should show Just a FormControl demo', function() { - select.getAttribute('value').then(function(demo: string) { - expect(demo).toBe('Just a FormControl Demo'); - }); - }); - - it('should show header', function() { - let header = element(by.css('app-hero-detail-1 > h3')); - expect(header.getText()).toBe('Just a FormControl'); - }); - - it('should show a form for hero information', function() { - let nameInput = element(by.css('input')); - expect(nameInput.getAttribute('value')).toBe(''); - }); - - }); // Just a FormControl demo test - - -}); // reactive forms + function getInput(key: string) { + return element(by.css(`input[formcontrolname=${key}`)); + } +}); diff --git a/aio/content/examples/reactive-forms/final.stackblitz.json b/aio/content/examples/reactive-forms/final.stackblitz.json deleted file mode 100644 index f789236245..0000000000 --- a/aio/content/examples/reactive-forms/final.stackblitz.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "description": "Angular Reactive Forms (final)", - "files":[ - "src/styles.css", - - "src/app/app.component.ts", - "src/app/app.component.html", - "src/app/app.component.css", - "src/app/app.module.ts", - "src/app/data-model.ts", - "src/app/hero.service.ts", - "src/app/hero-detail/hero-detail.component.html", - "src/app/hero-detail/hero-detail.component.ts", - "src/app/hero-detail/hero-detail.component.css", - "src/app/hero-list/hero-list.component.html", - "src/app/hero-list/hero-list.component.ts", - "src/app/hero-list/hero-list.component.css", - - "src/main-final.ts", - "src/index-final.html" - ], - "main": "src/index-final.html", - "tags": ["reactive", "forms"] -} diff --git a/aio/content/examples/reactive-forms/src/app/app.component.1.html b/aio/content/examples/reactive-forms/src/app/app.component.1.html index 14316fbe62..57ca7e22fb 100644 --- a/aio/content/examples/reactive-forms/src/app/app.component.1.html +++ b/aio/content/examples/reactive-forms/src/app/app.component.1.html @@ -1,4 +1,10 @@ -
Form value: {{ heroForm.value | json }}
- - - - diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-2.component.ts b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-2.component.ts deleted file mode 100644 index 6508904ffa..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-2.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* tslint:disable:component-class-suffix */ -// #docregion imports -import { Component } from '@angular/core'; -import { FormControl, FormGroup } from '@angular/forms'; -// #enddocregion imports - -@Component({ - selector: 'app-hero-detail-2', - templateUrl: './hero-detail-2.component.html' -}) -// #docregion v2 -export class HeroDetailComponent2 { - heroForm = new FormGroup ({ - name: new FormControl() - }); -} -// #enddocregion v2 diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-3.component.html b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-3.component.html deleted file mode 100644 index 89c5513566..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-3.component.html +++ /dev/null @@ -1,16 +0,0 @@ - -Form value: {{ heroForm.value | json }}
-Form status: {{ heroForm.status | json }}
- diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-3.component.ts b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-3.component.ts deleted file mode 100644 index 81388c8faa..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-3.component.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* tslint:disable:component-class-suffix */ -// #docregion imports -import { Component } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -// #enddocregion imports - -@Component({ - selector: 'app-hero-detail-3', - templateUrl: './hero-detail-3.component.html' -}) -// #docregion v3 -export class HeroDetailComponent3 { - heroForm: FormGroup; // <--- heroForm is of type FormGroup - - constructor(private fb: FormBuilder) { // <--- inject FormBuilder - this.createForm(); - } - - createForm() { - // #docregion required - this.heroForm = this.fb.group({ - name: ['', Validators.required ], - }); - // #enddocregion required - } -} -// #enddocregion v3 diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-3a.component.ts b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-3a.component.ts deleted file mode 100644 index 7cc0b1ca8f..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-3a.component.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* tslint:disable:component-class-suffix */ -// #docregion imports -import { Component } from '@angular/core'; -import { FormBuilder, FormGroup } from '@angular/forms'; -// #enddocregion imports - -@Component({ - selector: 'app-hero-detail-3', - templateUrl: './hero-detail-3.component.html' -}) -// #docregion v3a -export class HeroDetailComponent3 { - heroForm: FormGroup; // <--- heroForm is of type FormGroup - - constructor(private fb: FormBuilder) { // <--- inject FormBuilder - this.createForm(); - } - - createForm() { - this.heroForm = this.fb.group({ - name: '', // <--- the FormControl called "name" - }); - } -} -// #enddocregion v3a diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-4.component.html b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-4.component.html deleted file mode 100644 index 8702eeb540..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-4.component.html +++ /dev/null @@ -1,46 +0,0 @@ - -Form value: {{ heroForm.value | json }}
diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-4.component.ts b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-4.component.ts deleted file mode 100644 index b9a61aa1ea..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-4.component.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* tslint:disable:component-class-suffix */ -// #docregion imports -import { Component } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; - -import { states } from '../data-model'; -// #enddocregion imports - -@Component({ - selector: 'app-hero-detail-4', - templateUrl: './hero-detail-4.component.html' -}) -// #docregion v4 -export class HeroDetailComponent4 { - heroForm: FormGroup; - states = states; - - constructor(private fb: FormBuilder) { - this.createForm(); - } - - createForm() { - this.heroForm = this.fb.group({ - name: ['', Validators.required ], - street: '', - city: '', - state: '', - zip: '', - power: '', - sidekick: '' - }); - } -} -// #enddocregion v4 diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-5.component.html b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-5.component.html deleted file mode 100644 index bc73ce006e..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-5.component.html +++ /dev/null @@ -1,56 +0,0 @@ - - - -heroForm value: {{ heroForm.value | json}}
-Name value: {{ heroForm.get('name').value }}
- - - -Street value: {{ heroForm.get('address.street').value}}
- diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-5.component.ts b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-5.component.ts deleted file mode 100644 index 1193265c5b..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-5.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* tslint:disable:component-class-suffix */ -import { Component } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; - -import { states } from '../data-model'; - -@Component({ - selector: 'app-hero-detail-5', - templateUrl: './hero-detail-5.component.html' -}) -// #docregion v5 -export class HeroDetailComponent5 { - heroForm: FormGroup; - states = states; - - constructor(private fb: FormBuilder) { - this.createForm(); - } - - createForm() { - this.heroForm = this.fb.group({ // <-- the parent FormGroup - name: ['', Validators.required ], - address: this.fb.group({ // <-- the child FormGroup - street: '', - city: '', - state: '', - zip: '' - }), - power: '', - sidekick: '' - }); - } -} -// #enddocregion v5 - diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-6.component.html b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-6.component.html deleted file mode 100644 index a6f352a9b9..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-6.component.html +++ /dev/null @@ -1,46 +0,0 @@ - -Form value: {{ heroForm.value | json }}
diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-6.component.ts b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-6.component.ts deleted file mode 100644 index 042b21aaf7..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-6.component.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* tslint:disable:component-class-suffix */ -// #docregion import-input -import { Component, Input, OnChanges } from '@angular/core'; -// #enddocregion import-input -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; - -// #docregion import-hero -import { Hero, states } from '../data-model'; -// #enddocregion import-hero - -////////// 6 //////////////////// - -@Component({ - selector: 'app-hero-detail-6', - templateUrl: './hero-detail-5.component.html' -}) -// #docregion v6 -export class HeroDetailComponent6 implements OnChanges { - // #docregion hero - @Input() hero: Hero; - // #enddocregion hero - - heroForm: FormGroup; - states = states; - - constructor(private fb: FormBuilder) { - this.createForm(); - } - - createForm() { - // #docregion hero-form-model - this.heroForm = this.fb.group({ - name: ['', Validators.required ], - address: this.fb.group({ - street: '', - city: '', - state: '', - zip: '' - }), - power: '', - sidekick: '' - }); - // #enddocregion hero-form-model - } - - // #docregion patch-value-on-changes - ngOnChanges() { // <-- call rebuildForm in ngOnChanges - this.rebuildForm(); - } - // #enddocregion patch-value-on-changes - - // #docregion patch-value-rebuildform - rebuildForm() { // <-- wrap patchValue in rebuildForm - this.heroForm.reset(); - // #docregion patch-value - this.heroForm.patchValue({ - name: this.hero.name - }); - // #enddocregion patch-value - } - // #enddocregion patch-value-rebuildform -} - - - -// #enddocregion v6 diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-7.component.html b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-7.component.html deleted file mode 100644 index 57b00ca92c..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-7.component.html +++ /dev/null @@ -1,46 +0,0 @@ - -Form value: {{ heroForm.value | json }}
diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-7.component.ts b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-7.component.ts deleted file mode 100644 index b70b2e879d..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-7.component.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* tslint:disable:component-class-suffix */ -// #docplaster -// #docregion imports -import { Component, Input, OnChanges } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; - -// #docregion import-address -import { Address, Hero, states } from '../data-model'; -// #enddocregion import-address - -// #enddocregion imports - -@Component({ - selector: 'app-hero-detail-7', - templateUrl: './hero-detail-5.component.html' -}) -// #docregion v7 -export class HeroDetailComponent7 implements OnChanges { - @Input() hero: Hero; - - heroForm: FormGroup; - states = states; - - constructor(private fb: FormBuilder) { - this.createForm(); - } - - createForm() { - // #docregion address-form-group - this.heroForm = this.fb.group({ - name: ['', Validators.required ], - address: this.fb.group(new Address()), // <-- a FormGroup with a new address - power: '', - sidekick: '' - }); - // #enddocregion address-form-group - } - - // #docregion ngOnChanges - ngOnChanges() { - this.rebuildForm(); - } - // #enddocregion ngOnChanges - - // #docregion rebuildForm - rebuildForm() { - this.heroForm.reset({ - name: this.hero.name, - // #docregion set-value-address - address: this.hero.addresses[0] || new Address() - // #enddocregion set-value-address - }); - } - // #enddocregion rebuildForm - - /* First version of rebuildForm */ - rebuildForm1() { - // #docregion reset - this.heroForm.reset(); - // #enddocregion reset - // #docregion set-value - this.heroForm.setValue({ - name: this.hero.name, - address: this.hero.addresses[0] || new Address() - }); - // #enddocregion set-value - } -} diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-8.component.html b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-8.component.html deleted file mode 100644 index bfb591551e..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-8.component.html +++ /dev/null @@ -1,72 +0,0 @@ - -heroForm value: {{ heroForm.value | json}}
diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-8.component.ts b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-8.component.ts deleted file mode 100644 index f3e09df7fe..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail-8.component.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* tslint:disable:component-class-suffix */ -// #docregion imports -import { Component, Input, OnChanges } from '@angular/core'; -import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; - -import { Address, Hero, states } from '../data-model'; -// #enddocregion imports - -@Component({ - selector: 'app-hero-detail-8', - templateUrl: './hero-detail-8.component.html' -}) -// #docregion v8 -export class HeroDetailComponent8 implements OnChanges { - @Input() hero: Hero; - - heroForm: FormGroup; - states = states; - - // #docregion ctor - constructor(private fb: FormBuilder) { - this.createForm(); - this.logNameChange(); - } - // #enddocregion ctor - - createForm() { - // #docregion secretLairs-form-array - this.heroForm = this.fb.group({ - name: ['', Validators.required ], - secretLairs: this.fb.array([]), // <-- secretLairs as an empty FormArray - power: '', - sidekick: '' - }); - // #enddocregion secretLairs-form-array - } - - logNameChange() {/* Coming soon */} - - // #docregion onchanges - ngOnChanges() { - this.rebuildForm(); - } - // #enddocregion onchanges - - // #docregion rebuildform - rebuildForm() { - this.heroForm.reset({ - name: this.hero.name - }); - this.setAddresses(this.hero.addresses); - } -// #enddocregion rebuildform - - // #docregion get-secret-lairs - get secretLairs(): FormArray { - return this.heroForm.get('secretLairs') as FormArray; - }; - // #enddocregion get-secret-lairs - - // #docregion set-addresses - setAddresses(addresses: Address[]) { - const addressFGs = addresses.map(address => this.fb.group(address)); - const addressFormArray = this.fb.array(addressFGs); - this.heroForm.setControl('secretLairs', addressFormArray); - } - // #enddocregion set-addresses - - // #docregion add-lair - addLair() { - this.secretLairs.push(this.fb.group(new Address())); - } - // #enddocregion add-lair -} diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail.component.css b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail.component.css deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail.component.html b/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail.component.html deleted file mode 100644 index c5e77ba43d..0000000000 --- a/aio/content/examples/reactive-forms/src/app/hero-detail/hero-detail.component.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - -heroForm value: {{ heroForm.value | json}}
- - -+ Value: {{ name.value }} +
+ + + + ++ +
+ diff --git a/aio/content/examples/reactive-forms/src/app/name-editor/name-editor.component.ts b/aio/content/examples/reactive-forms/src/app/name-editor/name-editor.component.ts new file mode 100644 index 0000000000..b549b560ea --- /dev/null +++ b/aio/content/examples/reactive-forms/src/app/name-editor/name-editor.component.ts @@ -0,0 +1,22 @@ +// #docplaster +// #docregion create-control +import { Component } from '@angular/core'; +import { FormControl } from '@angular/forms'; + +@Component({ + selector: 'app-name-editor', + templateUrl: './name-editor.component.html', + styleUrls: ['./name-editor.component.css'] +}) +export class NameEditorComponent { + name = new FormControl(''); +// #enddocregion create-control + +// #docregion update-value + updateName() { + this.name.setValue('Nancy'); + } +// #enddocregion update-value +// #docregion create-control +} +// #enddocregion create-control diff --git a/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.1.html b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.1.html new file mode 100644 index 0000000000..c1fd2a10d2 --- /dev/null +++ b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.1.html @@ -0,0 +1,67 @@ + + + + + ++ Form Value: {{ profileForm.value | json }} +
+ + ++ +
+ \ No newline at end of file diff --git a/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.1.ts b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.1.ts new file mode 100644 index 0000000000..94d388847e --- /dev/null +++ b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.1.ts @@ -0,0 +1,40 @@ +// #docplaster +// #docregion formgroup, nested-formgroup +import { Component } from '@angular/core'; +// #docregion imports +import { FormGroup, FormControl } from '@angular/forms'; +// #enddocregion imports + +@Component({ + selector: 'app-profile-editor', + templateUrl: './profile-editor.component.html', + styleUrls: ['./profile-editor.component.css'] +}) +export class ProfileEditorComponent { +// #docregion formgroup-compare + profileForm = new FormGroup({ + firstName: new FormControl(''), + lastName: new FormControl(''), +// #enddocregion formgroup + address: new FormGroup({ + street: new FormControl(''), + city: new FormControl(''), + state: new FormControl(''), + zip: new FormControl('') + }) +// #docregion formgroup + }); +// #enddocregion formgroup, nested-formgroup, formgroup-compare +// #docregion patch-value + updateProfile() { + this.profileForm.patchValue({ + firstName: 'Nancy', + address: { + street: '123 Drew Street' + } + }); + } +// #enddocregion patch-value +// #docregion formgroup, nested-formgroup +} +// #enddocregion formgroup diff --git a/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.2.ts b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.2.ts new file mode 100644 index 0000000000..d482d70b01 --- /dev/null +++ b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.2.ts @@ -0,0 +1,58 @@ +// #docplaster +// #docregion form-builder +import { Component } from '@angular/core'; +// #docregion form-builder-imports +import { FormBuilder } from '@angular/forms'; +// #enddocregion form-builder-imports, form-builder +// #docregion form-array-imports +import { FormArray } from '@angular/forms'; +// #docregion form-builder-imports, form-builder +// #enddocregion form-builder-imports, form-array-imports + +@Component({ + selector: 'app-profile-editor', + templateUrl: './profile-editor.component.html', + styleUrls: ['./profile-editor.component.css'] +}) +export class ProfileEditorComponent { +// #docregion formgroup-compare + profileForm = this.fb.group({ + firstName: [''], + lastName: [''], + address: this.fb.group({ + street: [''], + city: [''], + state: [''], + zip: [''] + }), +// #enddocregion form-builder, formgroup-compare + aliases: this.fb.array([ + this.fb.control('') + ]) +// #docregion form-builder, formgroup-compare + }); +// #enddocregion form-builder, formgroup-compare + get aliases() { + return this.profileForm.get('aliases') as FormArray; + } + +// #docregion inject-form-builder, form-builder + + constructor(private fb: FormBuilder) { } +// #enddocregion inject-form-builder, form-builder + + updateProfile() { + this.profileForm.patchValue({ + firstName: 'Nancy', + address: { + street: '123 Drew Street' + } + }); + } + + addAlias() { + this.aliases.push(this.fb.control('')); + } +// #docregion form-builder +} +// #enddocregion form-builder diff --git a/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.css b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.css new file mode 100644 index 0000000000..6d29164b1a --- /dev/null +++ b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.css @@ -0,0 +1,39 @@ +/* ProfileEditorComponent's private CSS styles */ +:host { + display: flex; + flex-direction: column; + padding-top: 24px; +} + +label { + display: block; + width: 6em; + margin: .5em 0; + color: #607D8B; + font-weight: bold; +} + +input { + height: 2em; + font-size: 1em; + padding-left: .4em; +} + +button { + font-family: Arial; + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; +} + +button:hover { + background-color: #cfd8dc; +} + +button:disabled { + background-color: #eee; + color: #ccc; + cursor: auto; +} diff --git a/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.html b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.html new file mode 100644 index 0000000000..86178e1c3c --- /dev/null +++ b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.html @@ -0,0 +1,80 @@ + + + + ++ Form Value: {{ profileForm.value | json }} +
+ + + + ++ Form Status: {{ profileForm.status }} +
+ + + ++ +
+ diff --git a/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.ts b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.ts new file mode 100644 index 0000000000..813c97d5c0 --- /dev/null +++ b/aio/content/examples/reactive-forms/src/app/profile-editor/profile-editor.component.ts @@ -0,0 +1,73 @@ +// #docplaster +// #docregion form-builder +import { Component } from '@angular/core'; +// #docregion form-builder-imports +import { FormBuilder } from '@angular/forms'; +// #enddocregion form-builder-imports +// #docregion validator-imports +import { Validators } from '@angular/forms'; +// #enddocregion validator-imports +// #docregion form-array-imports +import { FormArray } from '@angular/forms'; +// #enddocregion form-array-imports + +@Component({ + selector: 'app-profile-editor', + templateUrl: './profile-editor.component.html', + styleUrls: ['./profile-editor.component.css'] +}) +export class ProfileEditorComponent { +// #docregion required-validator, aliases + profileForm = this.fb.group({ + firstName: ['', Validators.required], + lastName: [''], + address: this.fb.group({ + street: [''], + city: [''], + state: [''], + zip: [''] + }), +// #enddocregion form-builder, required-validator + aliases: this.fb.array([ + this.fb.control('') + ]) +// #docregion form-builder, required-validator + }); +// #enddocregion form-builder, required-validator, aliases +// #docregion aliases-getter + + get aliases() { + return this.profileForm.get('aliases') as FormArray; + } + +// #enddocregion aliases-getter +// #docregion inject-form-builder, form-builder + constructor(private fb: FormBuilder) { } + +// #enddocregion inject-form-builder + + updateProfile() { + this.profileForm.patchValue({ + firstName: 'Nancy', + address: { + street: '123 Drew Street' + } + }); + } +// #enddocregion form-builder +// #docregion add-alias + + addAlias() { + this.aliases.push(this.fb.control('')); + } +// #enddocregion add-alias +// #docregion on-submit + + onSubmit() { + // TODO: Use EventEmitter with form value + console.warn(this.profileForm.value); + } +// #enddocregion on-submit +// #docregion form-builder +} +// #enddocregion form-builder diff --git a/aio/content/examples/reactive-forms/src/index-final.html b/aio/content/examples/reactive-forms/src/index-final.html deleted file mode 100644 index 13416ffe40..0000000000 --- a/aio/content/examples/reactive-forms/src/index-final.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - -