# Scopes

## What's scopes?

If you want to ask user something, you need to use scope. Scope - an isolated place for the user, in which the handlers of ordinary controllers don't work, but only the handlers described in the scope work

## How it works?

You call the `.scope` **answer** method. Then all custom updates are handled by scope handlers, other handlers don't. You can leave at any time, just call the .unscope **answer** method

{% hint style="info" %}
`.scope` answer method takes argument: scope id (resource name), e.g. for NameScope class it will be 'name'. If you try to enter a scope with haven't id, you will get an error
{% endhint %}

## Example

{% code title="app.module.ts" %}

```typescript
import { Module } from 'nestgram';
import { AppService } from './app.service';
import { AppController } from './app.controller';
import { NameModule } from './scopes/name/name.module';

@Module({
  imports: [NameModule],
  controllers: [AppController],
  services: [AppService],
})
export class AppModule {}
```

{% endcode %}

{% code title="app.controller.ts" %}

```typescript
import { Answer, Controller, GetAnswer, Keyboard, KeyboardTypes, MessageSend, OnClick, OnCommand } from 'nestgram';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService?: AppService) {}

  @OnCommand('start')
  async start(@GetAnswer() answer: Answer) {
    try {
      return new MessageSend(
        'Hello! Do you want to enter your name?',
        new Keyboard(KeyboardTypes.underTheMessage)
          .btn('Enter my name', 'scope'),
      );
    } catch (e) {
      console.error(e);
    }
  }

  @OnClick('scope')
  async enterScope(@GetAnswer() answer: Answer) {
    await answer.scope('name');
    return 'Enter your name';
  }
}
```

{% endcode %}

{% code title="name.module.ts" %}

```typescript
import { Module } from 'nestgram';
import { NameScope } from './name.scope';
import { NameService } from './name.service';

@Module({
  scopes: [NameScope],
  services: [NameService],
})
export class NameModule {}
```

{% endcode %}

{% code title="name.scope.ts" %}

```typescript
import { Answer, GetAnswer, Keyboard, KeyboardTypes, MessageSend, OnClick, OnText, Scope, Text } from 'nestgram';

@Scope()
export class NameScope {
  @OnText()
  onNameSend(@Text() name: string) {
    return new MessageSend(
      `Hello, ${name}!`,
      new Keyboard(KeyboardTypes.underTheMessage)
        .btn('Leave scope', 'leave'),
    );
  }

  @OnClick('leave')
  async leaveScope(@GetAnswer() answer: Answer) {
    await answer.unscope();
    return 'Unscope';
  }
}
```

{% endcode %}

{% hint style="info" %}
You can read more about **Answer class** [here](https://degreetpro.gitbook.io/nestgram/nestgram-features/answer-class)

You can read more about **Keyboards** [here](https://degreetpro.gitbook.io/nestgram/keyboards/keyboard-types-building-keyboard)
{% endhint %}

## On scope enter event

You can handle when the user enters the scope with the **@OnEnter decorator**

{% code title="app.controller.ts" %}

```typescript
import { Answer, Controller, GetAnswer, Keyboard, KeyboardTypes, MessageSend, OnClick, OnCommand } from 'nestgram';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService?: AppService) {}

  @OnCommand('start')
  async start(@GetAnswer() answer: Answer) {
    try {
      return new MessageSend(
        'Hello! Do you want to enter your name?',
        new Keyboard(KeyboardTypes.underTheMessage)
          .btn('Enter my name', 'scope'),
      );
    } catch (e) {
      console.error(e);
    }
  }

  @OnClick('scope')
  async enterScope(@GetAnswer() answer: Answer) {
    await answer.scope('name');
  }
}
```

{% endcode %}

{% code title="name.scope.ts" %}

```typescript
import { Answer, GetAnswer, Keyboard, KeyboardTypes, MessageSend, OnClick, OnEnter, OnText, Scope, Text } from 'nestgram';

@Scope()
export class NameScope {
  @OnEnter()
  onScopeEnter() {
    return 'Enter your name';
  }

  @OnText()
  onNameSend(@Text() name: string) {
    return new MessageSend(
      `Hello, ${name}!`,
      new Keyboard(KeyboardTypes.underTheMessage)
        .btn('Leave scope', 'leave'),
    );
  }

  @OnClick('leave')
  async leaveScope(@GetAnswer() answer: Answer) {
    await answer.unscope();
    return 'Unscope';
  }
}
```

{% endcode %}
