Code News

AI Beat Humans at Reading! Maybe Not

Cancer Diagnosis from a Blood Draw? Liquid Biopsies Are Still a Dream

A New Way to Track Down Bugs Could Help Save IoT

'CS:GO' in Your Facebook Feed: One of the Biggest Esports Leagues Is Moving to Facebook. Why?

Mental Illness in the Web Industry

  • The picture of the tortured artist has endured for centuries: creative geniuses who struggle with their metaphorical demons and don’t relate to life the same way as most people. Today, we know some of this can be attributed to mental illness: depression, anxiety, bipolar disorder, and many others. We have modern stories about this and plenty of anecdotal information that fuels the popular belief in a link between creativity and mental illness.

    But science has also started asking questions about the link between mental illness and creativity. A recent study has suggested that creative professionals may be more genetically predisposed to mental illness. In the web industry, whether designer, dev, copywriter, or anything else, we’re often creative professionals. The numbers suggest that mental illness hits the web industry especially hard.

    Our industry has made great strides in compassionate discussion of disability, with a focus on accessibility and events like Blue Beanie Day. But even though we’re having meaningful conversations and we’re seeing progress, issues related to diversity, inclusion, and sexual harassment are still a major problem for our industry. Understanding and acceptance of mental health issues is an area that needs growth and attention just like many others.

    When it comes to mental health, we aren’t quite as understanding as we think we are. According to a study published by the Center of Disease Control, 57% of the general population believes that society at large is caring and sympathetic toward people with mental illness; but only 25% of people with mental health symptoms believed the same thing. Society is less understanding and sympathetic regarding mental illness than it thinks it is.

    Where’s the disconnect?  What does it look like in our industry? It’s usually not negligence or ill will on anybody’s part. It has a lot more to do with people just not understanding the prevalence and reality of mental illness in the workplace. We need to begin discussing mental illness as we do any other personal challenge that people face.

    This article is no substitute for a well-designed scientific study or a doctor’s advice, and it’s not trying to declare truths about mental illness in the industry. And it certainly does not intend to lump together or equalize any and all mental health issues, illnesses, or conditions. But it does suspect that plenty of people in the industry struggle with their mental health at some point or another, and we just don’t seem to talk about it. This doesn’t seem to make sense in light of the sense of community that web professionals have been proud of for decades.

    We reached out to a few people in our industry who were willing to share their unique stories to bring light to what mental health looks like for them in the workplace. Whether you have your own struggles with mental health issues or just want to understand those who do, these stories are a great place to start the conversation.

    Meet the contributors

    Gerry: I’ve been designing websites since the late ‘90s, starting out in UI design, evolving into an IA, and now in a UX leadership role. Over my career, I’ve contributed to many high-profile projects, organized local UX events, and done so in spite of my personal roadblocks.

    Brandon Gregory: I’ve been working in the web industry since 2006, first as a designer, then as a developer, then as a manager/technical leader. I’m also a staff member and regular contributor at A List Apart. I was diagnosed with bipolar disorder in 2002 and almost failed out of college because of it, although I now live a mostly normal life with a solid career and great family. I’ve been very open about my condition and have done some writing on it on Medium to help spread awareness and destigmatize mental illnesses.

    Stephen Keable: I’ve been building and running websites since 1999, both professionally and for fun. Worked for newspapers, software companies, and design agencies, in both permanent and freelance roles, almost always creating front-end solutions, concentrating on a user-centered approach.

    Bri Piccari: I’ve been messing around with the web since MySpace was a thing, figuring out how to customize themes and make random animations fall down from the top of my profile. Professionally, I’ve been in the field since 2010, freelancing while in college before transitioning to work at small agencies and in-house for a spell after graduation. I focus on creating solid digital experiences, employing my love for design with [a] knack for front-end development. Most recently, I started a small design studio, but decided to jump back into more steady contract and full-time work, after the stress of owning a small business took a toll on my mental health. It was a tough decision, but I had to do what was best for me. I also lead my local AIGA chapter and recently got my 200-hour-yoga-teacher certification.

    X: I also started tinkering with the web on Myspace, and started working on websites to help pay my way through college. I just always assumed I would do something else to make a living. Then, I was diagnosed with bipolar disorder. My [original non-web] field was not a welcoming and supportive place for that, so I had to start over, in more ways than one. The web industry hadn’t gone anywhere, and it’s always been welcoming to people with random educational histories, so I felt good about being able to make a living and staying healthy here. But because of my experience when I first tried to be open about my illness, I now keep it a secret. I’m not ashamed of it; in fact, it’s made me live life more authentically. For example, in my heart, I knew I wanted to work on the web the entire time.

    The struggle is real

    Mental health issues are as numerous and unique as the people who struggle with them. We asked the contributors what their struggles look like, particularly at work in the web industry.

    G: I have an interesting mix of ADD, dyslexia, and complex PTSD. As a result, I’m an incomplete person, in a perpetual state of self-doubt, toxic shame, and paralyzing anxiety. I’ve had a few episodes in my past where a requirement didn’t register or a criticism was taken the wrong way and I’ve acted less than appropriately (either through panic, avoidance, or anger). When things go wrong, I deal with emotional flashbacks for weeks.

    Presenting or reading before an audience is a surreal experience as well. I go into a zone where I’m never sure if I’m speaking coherently or making any sense at all until I’ve spoken with friends in the audience afterward. This has had a negative effect on my career, making even the most simple tasks anxiety-driven.

    BG: I actually manage to at least look like I have everything together, so most people don’t know I have bipolar until I tell them. On the inside, I struggle—a lot. There are bouts of depression where I’m exhausted all day and deal with physical pain, and bursts of mania where I take unnecessary risks and make inappropriate outbursts, and I can switch between these states with little or no notice. It’s a balancing act to be sure, and I work very hard to keep it together for the people in my life.

    SK: After the sudden death of my mother, I started suffering from panic attacks. One of which came on about 30 mins after getting to work, I couldn’t deal with the attack at work, so suddenly went home without telling anyone. Only phoning my boss from a lay-by after I’d been in tears at the side of the road for a while. The attacks also triggered depression, which has made motivation when I’m working from home so hard that I actually want to spend more time at the office. Luckily my employer is very understanding and has been really flexible.

    BP: Depending upon the time of year, I struggle greatly, with the worst making it nearly impossible to leave my apartment. As most folks often say, I’ve gotten rather good at appearing as though I’ve got my shit together—typically, most people I interact with have no idea what I’m going through unless I let them in. It wasn’t until recently that my mental health began to make a public appearance, as the stress of starting my own business and attempting to “have it all” made it tough to continue hiding it. There are definitely spans of time where depression severely affects my ability to create and interface with others, and “fake it till ya make it” doesn’t even cut it. I’m currently struggling with severe anxiety brought on by stress. Learning to manage that has been a process.

    X: I have been fortunate to be a high-functioning bipolar person for about 5 years now, so there really isn’t a struggle you can really see. The struggle is the stress and anxiety of losing that stability, and especially of people finding out. I take medication, have a routine, a support system, and a self-care regimen that is the reason why I am stable, but if work starts [to] erode my work-life balance, I can’t protect that time and energy anymore. In the past, this has started to happen when I’ve been asked to routinely pull all-nighters, work over the weekend, travel often, or be surrounded by a partying and drinking culture at work. Many people burn out under those conditions, but for me, it could be dangerous and send me into a manic episode, or even [make me] feel suicidal. I struggle with not knowing how far I can grow in my career, because a lot of the things you do to prove yourself and to demonstrate that you’re ready for more responsibility involves putting more on your plate. What’s the point of going after a big role if it’ll mean that I won’t be able to take care of myself? The FOMO [(fear of missing out)] gets bad.

    Making it work

    There are different ways that people can choose to—or choose not to—address the mental problems they struggle with. We’re ultimately responsible for making our own mental health decisions, and they are different for everyone. In the meantime, the rent has to get paid. Here’s how our contributors cope with their situations at work to make it happen.

    G: I started seeing a therapist, which has been an amazing help. I’ve also worked to change my attitude about criticism—I ask more clarifying questions, looking to define the problem, rather than get mad, defensive, or sarcastic. I’ve learned to be more honest with my very close coworkers, making them aware of my irrational shortcomings and asking for help. Also, because I’ve experienced trauma in personal and professional life, I’m hypersensitive to the emotions of others. Just being around a heated argument or otherwise heightened situation could put my body into a panic. I have to take extra special care in managing personalities, making sure everyone in a particular situation feels confident that they’re set up for success.

    BG: Medicine has worked very well for me, and I’m very lucky in that regard. That keeps most of my symptoms at a manageable level. Keeping my regular schedule and maintaining some degree of normalcy is a huge factor in remaining stable. Going to work, sleeping when I should, and keeping some social appointments, while not always easy, keep me from slipping too far in either direction. Also, writing has been a huge outlet for me and has helped others to better understand my condition as well. Finding some way to express what you’re going through is huge.

    SK: I had several sessions of bereavement counseling to help with the grief. I also made efforts to try and be more physically active each day, even if just going for a short walk on my lunch break. Working had become a way of escaping everything else that was going on at the time. Before the depression I used to work from home two days a week, however found these days very hard being on my own. So I started working from the office every weekday. Thankfully, through all of this, my employer was incredibly supportive and simply told me to do what I need to do. And it’s made me want to stay where I work more than before, as I realize how lucky I am to have their support.

    BP: Last winter I enrolled in a leadership/yoga teacher training [program] with a goal of cultivating a personal practice to better manage my depression and anxiety. Making the jump to be in an uncomfortable situation and learn the value of mindfulness has made a huge difference in my ability to cope with stress. Self-care is really big for me, and being aware of when I need to take a break. I’ve heard it called high-functioning depression and anxiety. I often take on too much and learning to say no has been huge. Therapy and a daily routine have been incredibly beneficial as well.

    X: The biggest one is medicine, it’s something I will take for the rest of my life and it’s worth it to me. I did a form of therapy called Dialectical Behavioral Therapy for a couple of years. The rest is a consistent regimen of self-care, but there are a couple of things that are big for work. Not working nights or weekends, keeping it pretty 9–5. Walking to and from the office or riding my bike. I started a yoga practice immediately after getting diagnosed, and the mental discipline it’s given me dampens the intensity of how I react to stressful situations at work. This isn’t to say that I will refuse to work unless it’s easy. Essentially, if something catches on fire, these coping strategies help me keep my shit together for long enough to get out.

    Spreading awareness

    There are a lot of misconceptions about mental illness, in the web industry as much as anywhere else. Some are benign but annoying; others are pretty harmful. Here are some of the things we wish others knew about us and our struggles.

    G: Nothing about my struggle is rational. It seems as if my body is wired to screw everything up and wallow in the shame of it. I have to keep moving, working against myself to get projects as close to perfect as possible. However, I am wired to really care about people, and that is probably why I’ve been successful in UX.

    BG: Just because I look strong doesn’t mean I don’t need support. Just because I have problems doesn’t mean I need you to solve them. Sometimes, just checking in or being there is the best thing for me. I don’t want to be thought of as broken or fragile (although I admit, sometimes I am). I am more than my disorder, but I can’t completely ignore it either.

    Also, there are still a lot of stigmas surrounding mental illness, to the point that I didn’t feel safe admitting to my disorder to a boss at a previous job. Mental illnesses are medical conditions that are often classified as legitimate disabilities, but employees may not be safe admitting that they have one—that’s the reality we live with.

    SK: For others who are going through grief-related depression, I would say that talking about it with friends, family, and even strangers helps you process it a lot. And the old cliché that time is a healer really is true. Also, for any employers, be supportive [of those] with mental health conditions—as supportive as you would [be of those] with physical health situations. They will pay you back.

    BP: I am a chronically ambitious human. Oftentimes, this comes from a place of working and doing versus dealing with what is bothering or plaguing me at the time. Much of my community involvement came from a place of needing a productive outlet. Fortunately or unfortunately, I have accomplished a lot through that—however, there are times where I simply need a break. I’m learning to absorb and understand that, as well as become OK with it.

    X: I wish people knew how much it bothers me to hear the word bipolar being used as an adjective to casually describe things and people. It’s not given as a compliment, and it makes it less likely that I will ever disclose my illness publicly. I also wish people knew how many times I’ve come close to just being open about it, but held back because of the other major diversity and inclusion issues in the tech industry. Women have to deal with being called moody and erratic. People stereotype the ethnic group I belong to as being fiery and ill-tempered. Why would I give people another way to discriminate against me?

    4 days 20 hours ago

Design Patterns for Cocoa: MVC and MVVM

  • Design patterns make your app's code more modular and forgiving when it comes to bug fixes and changes. In this article, you'll be learning about the MVC (Model-View-Controller) and the MVVM (Model-View-ViewModel) design patterns.

    Although design patterns (also known as architectural patterns) are key for the development of scalable Cocoa Touch apps, there is a lot of controversy around which architectural pattern is actually best for use in your app. 

    Check out these recent posts by Bart Jacobs on MVC and MVVM for more perspectives on these design patterns and the choice between them.

    The collection of objects of a certain [architectural pattern] in an application is sometimes referred to as a layer—for example, model layer. — Apple

    Without further ado, let's take a look at a few of the design patterns that you can use in your next app.

    MVC (Model-View-Controller)

    This is the most commonly used pattern in Cocoa Touch development, and it's also my personal favorite. This design pattern efficiently and effectively sorts out your code into three categories (or layers): the Model, the View, and the Controller.

    How Does It Work and Why Should I Use It?

    With this design pattern, you can make changes to one layer without affecting the other layers of the pattern. For example, if you need to change the database, you'd just remove the model and replace it without having to edit the view or controller. Or if you want to change the way a view looks, you don't have to worry about messing up the database code. This is called "separation of concerns", and it makes your code easier to debug, maintain, and reuse.

    In addition, this is the design pattern that is recommended by Apple themselves, and it's a norm in the iOS development community. If you're just starting out, I highly recommend just sticking to this pattern. You can try out different design patterns later in your Cocoa development career.

    Layers and Responsibilities

    Let's take a closer look at the different layers in this pattern and what each one is responsible for. Here's a quick diagram of the interactions between the layers:

    The MVC design pattern separates each part of your code into one of three parts: the Model, the View, and the Controller. 

    • Model: This layer is only responsible for the data and its form as it appears in your app. The Controller layer can make changes to the app data by notifying the model. The model is not responsible for anything else, including how the data is shown to the user or who or what uses the data.
    • View: The View is responsible for the representation of the data—only how the user sees and interacts with the data. This can include reusable cells, tables, and other user interface elements which know nothing about the data or how it's being handled. The data is supplied to the view elements by the Controller.
    • Controller: The Controller is the star of the show. It brings data from the Model and then passes it on to the View to be displayed to the user. This is the only layer between the Model and the View, which can cause some issues, which we'll look into later in this article. The Controller is typically implemented in ViewController.swift, and it is responsible for listening to input and changing the model as needed.

    One thing to keep in mind is that you shouldn't cram too many responsibilities into any one of these layers because that would defeat the purpose of having a design pattern!

    Also, if you don't keep the connections between the layers clean and clear, you'll end up with a messy and unmaintainable app, despite using the MVC design pattern! In particular, make sure you don't let the view and the model communicate directly. These interactions must happen solely through the Controller.

    MVVM (Model-View-ViewModel)

    Although the Model-View-Controller design pattern is pretty common and should work for most cases, it comes with its own set of challenges and drawbacks. Because of this, we have another design pattern called MVVM, which stands for Model-View-ViewModel.

    MVC Is Great, So Why Do I Need MVVM?

    Well, there's one major problem which you should be aware of. As you saw in the previous section, the Controller layer is the only layer between the View and the Model, so it's not surprising that people abuse this layer and quickly give it too many things to do. This might seem like the easiest thing to do at the time, because it avoids changing the other layers, but eventually it leads to a bloated Controller and difficult-to-maintain code.

    This has led to MVC being given the whimsical nickname "Massive-View-Controller" in some circles.

    The MVVM architectural pattern, which was borrowed by Cocoa developers from Microsoft, can help combat this problem of massive view controllers. Though it isn't as common in iOS development as MVC, it's increasingly being used to make up for the shortcomings of MVC.

    Layers and Responsibilities

    Let's take a look at the different layers and their responsibilities in MVVM. (You should probably note that in the Cocoa community, there aren't any formal guidelines on how to use these layers.) 

    Here's a quick diagram demonstrating the layers of this architectural pattern and their connections to one another.

    If you think about it, you'll see that even though views and controllers are separate layers in the MVC design pattern, they are very closely coupled. So in MVVM, we simply take the View and the Controller and combine them into one layer. 

    Let's compare each layer to its counterpart in the MVC pattern. 

    • (View) Controller: This layer, usually just known as the View, is tightly connected with the Controller. So much so that they aren't even separated into different layers! The View only communicates with the Controller, but the Controller communicates with the ViewModel and the View. The View and the Controller do the same tasks as in MVC, but the difference is that some tasks which were given to the Controller (in MVC) are now handled by an intermediate layer, the ViewModel, to prevent misuse of the Controller. The View still handles the display of data to the user, and the Controller responds to user events and communicates with the rest of the layers of the pattern.
    • ViewModel: This layer does not actually contain any "views" on its own, but instead handles the logic behind showing views—usually called presentation logic. This includes creating custom formatting and processing strings to display, as well as actually crunching numbers to be shown to the user based on the data in the Model layer. 
    • Model: The Model isn't very different the Model layer in the MVC pattern. As we saw before, the Model only handles the data and makes changes to that data if it receives updates from the ViewModel layer. It does not know anything about who's using the data, what they're doing with it, or how the user sees the data.

    As you've seen previously, you shouldn't mix the responsibilities of any of these layers as this can cause your app code to spiral in complexity, making the use of any design pattern redundant.

    Conclusion

    I hope you enjoyed learning more about these foundational design patterns for iOS. Hopefully, you gained a better understanding of the MVC and MVVM design patterns and are confident enough to use these in your future applications. 

    Of course, the architectural pattern which you use for your app is totally up to you, and it depends on the type of application that you're trying to develop. However, if you're new to iOS development, I still highly recommend sticking to the MVC design pattern because it is still the most mainstream in Cocoa development.

    While you're still here, be sure to check out some of our other tutorials and articles here on Envato Tuts+!

    4 days 21 hours ago

Building Games With Python 3 and Pygame: Part 4

  • Overview

    This is part four of a five-part series of tutorials about making games with Python 3 and Pygame. In part three, we dove into the heart of Breakout and learned how to handle events, met the main Breakout class, and saw how to move the different game objects.

    In this part, we will see how to detect collisions and what happens when the ball hits various objects like the paddle, the bricks, the walls, the ceiling, and the floor. Finally, we will review the important topic of game UI and in particular how to create a menu with our own custom buttons.

    Collision Detection

    In games, things bump into each other. Breakout is no different. Mostly it's the ball that bumps into stuff. The handle_ball_collisions() method has a nested function called intersect(), which is used to test if the ball hit an object and where it hit the object. It returns 'left', 'right', 'top', 'bottom', or None if the ball didn't hit the object.

    def handle_ball_collisions(self): def intersect(obj, ball): edges = dict( left=Rect(obj.left, obj.top, 1, obj.height), right=Rect(obj.right, obj.top, 1, obj.height), top=Rect(obj.left, obj.top, obj.width, 1), bottom=Rect(obj.left, obj.bottom, obj.width, 1)) collisions = set(edge for edge, rect in edges.items() if ball.bounds.colliderect(rect)) if not collisions: return None if len(collisions) == 1: return list(collisions)[0] if 'top' in collisions: if ball.centery >= obj.top: return 'top' if ball.centerx < obj.left: return 'left' else: return 'right' if 'bottom' in collisions: if ball.centery >= obj.bottom: return 'bottom' if ball.centerx < obj.left: return 'left' else: return 'right'Hitting the Ball With the Paddle

    When the ball hits the paddle, it bounces off. If it hits the top of the paddle, it will bounce back up but keep the same horizontal speed component. 

    But if it hits the side of the paddle, it will bounce to the opposite side (left or right) and continue its motion downward until it hits the floor. The code uses the intersect function().

    # Hit paddle s = self.ball.speed edge = intersect(self.paddle, self.ball) if edge is not None: self.sound_effects['paddle_hit'].play() if edge == 'top': speed_x = s[0] speed_y = -s[1] if self.paddle.moving_left: speed_x -= 1 elif self.paddle.moving_left: speed_x += 1 self.ball.speed = speed_x, speed_y elif edge in ('left', 'right'): self.ball.speed = (-s[0], s[1])Hitting the Floor

    When the paddle misses the ball on its way down (or if the ball hits the paddle on its side), the ball will keep falling and eventually hit the floor. At this point, the player loses a life, and the ball is recreated so the game can continue. The game is over when the player has run out of lives.

    # Hit floor if self.ball.top > c.screen_height: self.lives -= 1 if self.lives == 0: self.game_over = True else: self.create_ball()Hitting the Ceiling and Walls

    When the ball hits a wall or the ceiling, it simply bounces back. 

    # Hit ceiling if self.ball.top < 0: self.ball.speed = (s[0], -s[1]) # Hit wall if self.ball.left < 0 or self.ball.right > c.screen_width: self.ball.speed = (-s[0], s[1])Hitting Bricks

    When a ball hits a brick, it's a major event in Breakout—the brick disappears, the player gets a point, the ball bounces back, and a few other things happen (sound effect and possibly a special effect too) that I'll discuss later. 

    To determine if a brick was hit, the code checks to see if any of the bricks intersects with the ball:

    # Hit brick for brick in self.bricks: edge = intersect(brick, self.ball) if not edge: continue self.bricks.remove(brick) self.objects.remove(brick) self.score += self.points_per_brick if edge in ('top', 'bottom'): self.ball.speed = (s[0], -s[1]) else: self.ball.speed = (-s[0], s[1])Programming the Game Menu

    Most games have some UI. Breakout has a simple menu that has two buttons that say 'PLAY' and 'QUIT'. The menu shows up at the beginning of the game and disappears when the player clicks 'PLAY'. Let's see how the buttons and menu are implemented and how they integrate with the game.

    Making Buttons

    Pygame doesn't have a built-in UI library. There are third-party extensions, but I decided to build my own buttons for the menu. A button is a game object that has three states: normal, hover, and pressed. The normal state is when the mouse isn't over the button, and the hover state is when the mouse is over the button but the left mouse button isn't pressed. The pressed state is when the mouse is over the button and the player has pressed the left mouse button. 

    The button is implemented as a rectangle with background color and text displayed over it. The button also receives an on_click function (defaults to a noop lambda function) that gets called when the button is clicked.

    import pygame from game_object import GameObject from text_object import TextObject import config as c class Button(GameObject): def __init__(self, x, y, w, h, text, on_click=lambda x: None, padding=0): super().__init__(x, y, w, h) self.state = 'normal' self.on_click = on_click self.text = TextObject(x + padding, y + padding, lambda: text, c.button_text_color, c.font_name, c.font_size) def draw(self, surface): pygame.draw.rect(surface, self.back_color, self.bounds) self.text.draw(surface)

    The button handles its own mouse events and changes its internal state based on these events. When the button is in pressed state and receives a MOUSEBUTTONUP event, it means the player clicked the button, and the on_click() function is invoked.

    def handle_mouse_event(self, type, pos): if type == pygame.MOUSEMOTION: self.handle_mouse_move(pos) elif type == pygame.MOUSEBUTTONDOWN: self.handle_mouse_down(pos) elif type == pygame.MOUSEBUTTONUP: self.handle_mouse_up(pos) def handle_mouse_move(self, pos): if self.bounds.collidepoint(pos): if self.state != 'pressed': self.state = 'hover' else: self.state = 'normal' def handle_mouse_down(self, pos): if self.bounds.collidepoint(pos): self.state = 'pressed' def handle_mouse_up(self, pos): if self.state == 'pressed': self.on_click(self) self.state = 'hover'

    The back_color property that is used to draw the background rectangle always returns the color that matches the current state of the button, so it's clear to the player the button is active:

    @property def back_color(self): return dict(normal=c.button_normal_back_color, hover=c.button_hover_back_color, pressed=c.button_pressed_back_color)[self.state]Creating the Menu

    The create_menu() function creates a menu with two buttons with the text 'PLAY' and 'QUIT'. It has two nested functions called on_play() and on_quit() that it provides to the corresponding button. Each button is added to the objects list (to be drawn) and also to the menu_buttons field.

    def create_menu(self): for i, (text, handler) in enumerate((('PLAY', on_play), ('QUIT', on_quit))): b = Button(c.menu_offset_x, c.menu_offset_y + (c.menu_button_h + 5) * i, c.menu_button_w, c.menu_button_h, text, handler, padding=5) self.objects.append(b) self.menu_buttons.append(b) self.mouse_handlers.append(b.handle_mouse_event)

    When the PLAY button is clicked, on_play() is invoked, which removes the buttons from the objects list so they are not drawn anymore. Also, the boolean fields that trigger the start of the game—is_game_running and start_level—are set to True. 

    When the QUIT button is clicked, is_game_running is set to False (effectively pausing the game) and game_over is set to True, triggering the end game sequence.

    def on_play(button): for b in self.menu_buttons: self.objects.remove(b) self.is_game_running = True self.start_level = True def on_quit(button): self.game_over = True self.is_game_running = FalseShowing and Hiding the Game Menu

    Showing and hiding the menu is implicit. When the buttons are in the objects list, the menu is visible; when they are removed, it is hidden. As simple as that. 

    It is possible to create a nested menu with its own surface that renders sub-components like buttons and more, and then just add/remove that menu component, but it's not needed for this simple menu.

    Conclusion

    In this part, we covered collision detection and what happens when the ball hits various objects like the paddle, the bricks, the walls, the ceiling, and the floor. Also, we created our own menu with custom buttons that we hide and show on command. 

    In the last part of the series, we will look into the end game, keeping tabs on score and lives, sound effects, and music.

    Then, we will develop a sophisticated system of special effects that will spice up the game. Finally, we will discuss the future direction and potential improvements.

    4 days 21 hours ago

Introduction to Forms in Angular 4: Writing Custom Form Validators

  • This is the third part of the series on creating forms in Angular. In the first two tutorials, we used Angular's template-driven and model-driven approach to create forms. However, while detailing both the approaches, there was something that we didn't cover—custom validator functions. This tutorial will cover everything you need to know about writing custom validators that meet your requirements.

    Prerequisites

    You don’t need to have followed part one or two of this series for part three to make sense. However, if you are entirely new to forms in Angular, you should head over to the first tutorial of this series and start from there. 

    Otherwise, grab a copy of this code from our GitHub repo and use that as a starting point.  

    Built-in Validators

    Angular doesn't boast a huge built-in validator library. As of Angular 4, we have the following popular validators in Angular:

    • required
    • minlength
    • maxlength
    • pattern

    There are actually a few more, and you can see the full list in the Angular docs

    We can use the above built-in validators in two ways:

    1. As directives in template-driven forms.

    <input name="fullName" ngModel required>

    2. As validators inside the FormControl constructor in model-driven forms.

    name = new FormControl('', Validators.required)

    If the above syntax doesn't make sense, follow my previous tutorials on building a signup form using a template-driven approach or a model-driven approach and then drop back!

    The built-in form validators hardly cover all the validation use cases that might be required in a real-world application. For instance, a signup form might need to check whether the values of the password and confirm password control fields are equal and display an error message if they don't match. A validator that blacklists emails from a particular domain is another common example. 

    Here is a fact: Template-driven forms are just model-driven forms underneath. In a template-driven form, we let the template take care of the model creation for us. The obvious question now is, how do you attach a validator to a form?

    Validators are just functions. In a model-driven form, attaching validators to FormControl is straightforward. In a template-driven form, however, there is a bit more work to be done. In addition to the validator function, you will need to write a directive for the validator and create instances of the directive in the template.

    Diving Into the Details

    Although this has been already covered, we will go through a quick recap of the code for the signup form. First, here's the reactive approach.

    app/signup-form/signup-form.component.ts // Use the formbuilder to build the Form model this.signupForm = this.fb.group({ email: ['',[Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$')]], password: this.fb.group({ pwd: ['', [Validators.required, Validators.minLength(8)]], confirmPwd: ['', [Validators.required, Validators.minLength(8) ]] }, { validator: PasswordMatch }), gender: ['', Validators.required], })

    FormBuilder is a syntax sugar that creates the FormGroup and FormControl instances. A FormControl tracks the value and the validation status of an individual form element. A FormGroup, on the other hand, comprises a group of FormControl instances, and it tracks the value and validity of the whole group.

    Here's the structure that we have been following:

    FormGroup -> 'signupForm' FormControl -> 'email' FormGroup -> 'password' FormControl -> 'pwd' FormControl -> 'confirmPwd' FormControl -> 'gender'

    Depending on the requirements, we can attach a validator to a FormControl or a FormGroup. An email blacklisting validator would require it to be attached to the FormControl instance of the email. 

    However, for more complex validations where multiple control fields have to be compared and validated, it's a better idea to add the validation logic to the parent FormGroup. As you can see, password has a FormGroup of its own, and this makes it easy for us to write validators that check the equality of pwd and confirmPwd.

    For the template-driven form, all that logic goes into the HTML template, and here is an example:

    app/signup-form/signup-form.component.html<form novalidate (ngSubmit)="onFormSubmit(signupForm)" #signupForm="ngForm"> <!-- Email input block --> <input type="text" [ngModel] = "user.email" name="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" required> <!-- Password block --> <div ngModelGroup="password"> <input type="password" ngModel name="pwd" minlength ="8" required > <input type="password" class="form-control" ngModel name="confirmPwd" > </div> ... <!-- Select Gender block --> <select id="select" class="form-control" [ngModel] = "user.gender" name = "gender" required> </select> </form>

    ngModel creates an instance of FormControl and binds it to a form control element. Similarly, ngModelGroup creates and binds a FormGroup instance to a DOM element. They share the same model domain structure discussed above. 

    It's also interesting to note that FormControl, FormGroup, and FormArray extend the AbstractControl class. What this means is that the AbstractControl class is responsible for tracking the values of form objects, validating them, and powering other things such as pristine, dirty, and touched methods. 

    Now that we are acquainted with both the form techniques, let's write our first custom validator.

    Custom Validator Function for Model-Driven Forms

    Validators are functions that take a FormControl/FormGroup instance as input and return either null or an error object. null is returned when the validation is successful, and if not, the error object is thrown. Here's a very basic version of a validation function. 

    app/password-match.tsimport { FormGroup } from '@angular/forms'; export function passwordMatch( control: FormGroup):{[key: string]: boolean} { }

    I've declared a function that accepts an instance of FormGroup as an input. It returns an object with a key of type string and a true/false value. This is so that we can return an error object of the form below:

    { mismatch: true }

    Next, we need to get the value of the pwd and confirmPwd FormControl instances. I am going to use control.get() to fetch their values. 

    export function passwordMatch (control: FormGroup):{[key: string]: boolean} { //Grab pwd and confirmPwd using control.get const pwd = control.get('pwd'); const confirmPwd = control.get('confirmPwd'); }

    Now we need to make the comparison and then return either null or an error object.

    app/password-match.tsimport { AbstractControl } from '@angular/forms'; export function passwordMatch (control: AbstractControl):{[key: string]: boolean} { //Grab pwd and confirmPwd using control.get const pwd = control.get('pwd'); const confirmPwd = control.get('confirmPwd'); // If FormControl objects don't exist, return null if (!pwd || !confirmPwd) return null; //If they are indeed equal, return null if (pwd.value === confirmPwd.value) { return null; } //Else return false return { mismatch: true }; }

    Why did I replace FormGroup with AbstractControl? As you know, AbstractControl is the mother of all Form* classes, and it gives you more control over the form control objects. It has the added benefit that it makes our validation code more consistent.

    Import the passwordMatch function in the SignupForm component and declare it as a validator for the password FormGroup instance.

    app/password-match.tsimport { passwordMatch } from './../password-match'; . . . export class SignupFormComponent implements OnInit { ngOnInit() { // Use the formbuilder to build the Form model this.signupForm = this.fb.group({ ... password: this.fb.group({ pwd: ['', [Validators.required, Validators.minLength(8)]], confirmPwd: ['', [Validators.required, Validators.minLength(8) ]] }, { validator: passwordMatch }), ... }) } } Displaying the Errors

    If you did everything right, password.errors?.mismatch will be true whenever the values of both the fields don't match.

    {{ password.errors?.mismatch } json }}

    Although there are alternative ways to display errors, I am going to use the ngIf directive to determine whether an error message should be displayed or not.

    First, I am going to use ngIf to see if the password is invalid. 

    <!-- Password error block --> <div *ngIf="(password.invalid && password.touched)"> </div>

    We use password.touched to ensure that the user is not greeted with errors even before a key has been pressed.

    Next, I am going to use the ngIf ="expression; then a else b" syntax to display the right error.

    app/signup-form/signup-form.component.html <ng-container *ngIf="password.errors?.mismatch; then first else second"> </ng-container> <ng-template #first> Password do not match </ng-template> <ng-template #second> Password needs to be more than 8 characters </ng-template>

    There you have it, a working model of the validator that checks for password equality.

    Demo for Custom Validators in Model-Driven FormsCustom Validator Directive for Template-Driven Forms

    We will be using the same validator function that we created for the model-driven form earlier. However, we don't have direct access to instances of FormControl/FormGroup in a template-driven form. Here are the things that you will need to do to make the validator work:

    1. Create a PasswordMatchDirective that serves as a wrapper around the passwordMatch validator function. We will be registering the directive as a validator using the NG_VALIDATORS provider. More on this later.
    2. Attach the directive to the template form control. 

    Let's write the directive first. Here's what a directive looks like in Angular:

    app/password-match.tsimport { AbstractControl } from '@angular/forms'; export function passwordMatch (control: AbstractControl):{[key: string]: boolean} { //Grab pwd and confirmPwd using control.get const pwd = control.get('pwd'); const confirmPwd = control.get('confirmPwd'); // If FormControl objects don't exist, return null if (!pwd || !confirmPwd) return null; //If they are indeed equal, return null if (pwd.value === confirmPwd.value) { return null; } //Else return false return { mismatch: true }; } //PasswordMatchDirective @Directive({ selector: '', providers: [ ] }) export class PasswordMatchDirective { }

    The @Directive decorator is used to mark the class as an Angular directive. It accepts an object as an argument that specifies the directive configuration meta-data such as selectors for which the directive should be attached, and the list of Providers to be injected, etc. Let's fill in the directive meta-data:

    app/password-match.ts@Directive({ selector: '[passwordMatch][ngModelGroup]', //1 providers: [ //2 { provide: NG_VALIDATORS, useValue: passwordMatch, multi: true } ] }) export class PasswordMatchDirective { }
    1. The directive is now attached to all input controls that have the attributes ngModelGroup and passwordMatch. 
    2. We extend the built-in validators using the NG_VALIDATORS provider. As previously mentioned, NG_VALIDATORS is a provider that has an extensible collection of validators. The passwordMatch function that we created earlier is declared as a dependency. The multi: true sets this provider to be a multi-provider. What this means is that we will be adding to the existing collection of validators provided by NG_VALIDATORS.

    Now, add the directive to the declarations array in ngModule.

    app/app.module.ts... import {PasswordMatchDirective} from './password-match'; @NgModule({ declarations: [ AppComponent, SignupFormComponent, PasswordMatchDirective ], imports: [ BrowserModule, FormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } Displaying Error Messages

    To display the validation error messages, I am going to use the same template that we created for the model-driven forms.

    <!-- Password error block --> <div *ngIf="(userPassword.invalid && userPassword.touched)"> <ng-container *ngIf="userPassword.errors?.mismatch; then first else second"> </ng-container> <ng-template #first> Password do not match </ng-template> <ng-template #second> Password needs to be more than 8 characters </ng-template> </div> Demo for Custom Validators in Template-Driven FormsConclusion

    In this tutorial, we learned about creating custom Angular validators for forms in Angular. 

    Validators are functions that return null or an error object. In model-driven forms, we have to attach the validator to a FormControl/FormGroup instance, and that's it. The procedure was a bit more complex in a template-driven form because we needed to create a directive on top of the validator function. 

    If you're interested in continuing to learn more about JavaScript, remember to check out what we have in Envato Market.

    I hope that you've enjoyed this series on Forms in Angular. I would love to hear your thoughts. Share them through the comments. 

    4 days 22 hours ago

What CES and Detroit Taught Us About The Future Of Cars

The GE9X Jet Engine Is About to Get a Blast of Ice (For Safety's Sake)

Pages