অ্যাঙ্গুলারজেএস-এ মতামতের মধ্যে পরিবর্তন করার সময় সুযোগের মডেল বজায় রাখুন


152

আমি AngularJS শিখছি। আসুন আমার আছে বলে / view1 ব্যবহার My1Ctrl , এবং / view2 ব্যবহার My2Ctrl ; এটি ট্যাবগুলি ব্যবহার করে নেভিগেট করা যেতে পারে যেখানে প্রতিটি দর্শনটির নিজস্ব, তবে ভিন্ন রূপ রয়েছে।

আমি কীভাবে নিশ্চিত করব যে ভিউ 1 আকারে সন্নিবেশিত মানগুলি পুনরায় সেট করা হয় না, যখন কোনও ব্যবহারকারী চলে যায় এবং তারপরে ভিউ 1 তে ফিরে আসে ?

আমার অর্থ হ'ল দ্বিতীয় দর্শনটি কীভাবে মডেলটি ছেড়ে দিয়েছিল ঠিক সেই একই মডেলটির অবস্থা ধরে রাখতে পারে?

উত্তর:


174

এটি করার সর্বোত্তম উপায়টি কী তা খুঁজে বের করার জন্য আমি কিছুটা সময় নিয়েছি। পুরানো পৃষ্ঠায় ফিরে যাওয়ার জন্য যখন ব্যবহারকারী পৃষ্ঠাটি ছেড়ে দেয় এবং তারপরে পিছনে বোতাম টিপত তখন আমি এই রাজ্যটি রাখতে চাইতাম; এবং আমার সমস্ত ডেটা কেবল রুটস্কোপে রাখে না

চূড়ান্ত ফলাফলটি প্রতিটি নিয়ামকের জন্য একটি পরিষেবা থাকে । কন্ট্রোলারে, আপনার কেবলমাত্র ফাংশন এবং ভেরিয়েবল রয়েছে যা আপনি পরিষ্কার করেন না সেগুলি সম্পর্কে আপনার যত্ন নেওয়া উচিত।

নিয়ামকের জন্য পরিষেবা নির্ভরতা ইনজেকশন দ্বারা ইনজেকশনের হয়। পরিষেবাগুলি সিলেটলেট হিসাবে, তাদের ডেটা নিয়ন্ত্রণকারীর ডেটার মতো ধ্বংস হয় না।

পরিষেবাটিতে, আমার একটি মডেল রয়েছে। মডেলটির কেবলমাত্র ডেটা রয়েছে - কোনও ফাংশন নেই -। এটি চালিয়ে যাওয়ার জন্য এটিকে JSON থেকে পিছনে পিছনে রূপান্তর করা যায়। অধ্যবসায়ের জন্য আমি এইচটিএমএল 5 লোকালস্টোর ব্যবহার করেছি।

সবশেষে আমি ব্যবহার করেছি window.onbeforeunloadএবং $rootScope.$broadcast('saveState');সমস্ত পরিষেবাগুলিকে জানাতে পারি যে তাদের রাজ্যটি সংরক্ষণ করা উচিত এবং $rootScope.$broadcast('restoreState')তাদের রাষ্ট্রটি পুনরুদ্ধার করতে জানাতে (যখন ব্যবহারকারী পৃষ্ঠাটি ছেড়ে যায় এবং পৃষ্ঠায় যথাক্রমে ফিরে আসার জন্য পিছনে বোতাম টিপেন তখন ব্যবহৃত হয়)।

আমার ব্যবহারকারীর নিয়ন্ত্রণকারীর জন্য ব্যবহারকারীর পরিষেবা নামক পরিষেবা :

app.factory('userService', ['$rootScope', function ($rootScope) {

    var service = {

        model: {
            name: '',
            email: ''
        },

        SaveState: function () {
            sessionStorage.userService = angular.toJson(service.model);
        },

        RestoreState: function () {
            service.model = angular.fromJson(sessionStorage.userService);
        }
    }

    $rootScope.$on("savestate", service.SaveState);
    $rootScope.$on("restorestate", service.RestoreState);

    return service;
}]);

ইউজারকন্ট্রোলার উদাহরণ

function userCtrl($scope, userService) {
    $scope.user = userService;
}

এরপরে দৃশ্যটি এইভাবে বাঁধাই করে

<h1>{{user.model.name}}</h1>

আর এ অ্যাপ্লিকেশন মডিউল , রান ফাংশন মধ্যে আমি হ্যান্ডেল সম্প্রচার এর saveState এবং restoreState

$rootScope.$on("$routeChangeStart", function (event, next, current) {
    if (sessionStorage.restorestate == "true") {
        $rootScope.$broadcast('restorestate'); //let everything know we need to restore state
        sessionStorage.restorestate = false;
    }
});

//let everthing know that we need to save state now.
window.onbeforeunload = function (event) {
    $rootScope.$broadcast('savestate');
};

আমি যেমন উল্লেখ করেছি এই মুহুর্তে আসতে কিছুটা সময় নিয়েছে। এটি করার একটি খুব পরিষ্কার উপায়, তবে কৌণিক বিকাশকালে এমন কিছু করা আমার পক্ষে সন্দেহজনক যে প্রকৌশল কিছুটা সাধারণ বিষয়।

আমি আরও সহজ দেখতে চাই, তবে ব্যবহারকারীরা পৃষ্ঠাটি ছেড়ে যায় এবং ফিরে আসে সহ কন্ট্রোলারদের ধরে রাখার রাষ্ট্র পরিচালনা করার পরিষ্কার উপায় হিসাবে।


10
পৃষ্ঠাটি রিফ্রেশ করার সময় কীভাবে ডেটা স্থির রাখতে হবে তা বর্ণনা করে, রুট পরিবর্তিত হওয়ার পরে কীভাবে তা চালিয়ে নেওয়া যায় তাই এটি প্রশ্নের উত্তর দেয় না। এছাড়াও এটি এমন অ্যাপ্লিকেশনগুলির জন্য কাজ করবে না যা রুটগুলি ব্যবহার করে না। প্লাস এটি কোথায় sessionStorage.restoreStateসেট করা আছে তা দেখায় না "true"। পৃষ্ঠাটি সতেজ হয়ে উঠলে ডেটা ধরে রাখার সঠিক সমাধানের জন্য, এখানে দেখুন । রুট পরিবর্তিত হলে অবিরাম ডেটা বজায় রাখার জন্য কার্লোসকার্কামোর উত্তরটি দেখুন। আপনার যা দরকার তা হ'ল ডেটা কোনও পরিষেবাতে রাখা।
হুগো উড

2
এটি আপনি যেভাবে পরামর্শ দিয়েছেন ঠিক একইভাবে এটি কোনও পরিষেবাতে সঞ্চয় করুন views আকর্ষণীয়ভাবে যথেষ্ট, এটি উইন্ডো.অনফরেউনলোড লোড করে আপনি যেভাবে পরামর্শ দিচ্ছেন তেমনভাবে একটি পৃষ্ঠায় পরিবর্তনও বজায় থাকে। যদিও আমাকে ডাবল চেক করার জন্য ধন্যবাদ। এই উত্তরটি এক বছরেরও বেশি পুরানো এবং এটি এখনও কৌনিক দিয়ে জিনিসগুলি করার সহজতম উপায় বলে মনে হচ্ছে।
আন্তন

পুরানো হওয়া সত্ত্বেও এখানে ফিরে আসার জন্য আপনাকে ধন্যবাদ :)। নিশ্চিত হয়ে নিন যে আপনার সমাধানে উভয় মতামত এবং পৃষ্ঠাগুলি রয়েছে তবে কোন কোডটি কী উদ্দেশ্যে কাজ করে তা ব্যাখ্যা করে না এবং এটি পর্যাপ্ত পরিপূর্ণ নয় যে এটি ব্যবহারযোগ্য হতে পারে । আমি কেবল আরও প্রশ্নগুলি এড়াতে পাঠকদের সতর্ক করেছিলাম । আপনার উত্তরটি উন্নত করতে যদি আপনার সম্পাদনা করার সময় হয় তবে তা দুর্দান্ত হবে।
হুগো উড

পরিবর্তে এই আপনার নিয়ামক কী যদি: $scope.user = userService;আপনি ভালো কিছু আছে: $scope.name = userService.model.name; $scope.email = userService.model.email;। এটি কাজ করবে বা দেখুন ভেরিয়েবল পরিবর্তন করা কি সেবার এটি পরিবর্তন করবে না?
ক্রীড়া

2
আমি মনে করি যে
কৌণিকর

22

উত্তরের জন্য কিছুটা দেরি হলেও কিছু সেরা অনুশীলনের সাথে সবেমাত্র ফিডল আপডেট হয়েছে

jsfiddle

var myApp = angular.module('myApp',[]);
myApp.factory('UserService', function() {
    var userService = {};

    userService.name = "HI Atul";

    userService.ChangeName = function (value) {

       userService.name = value;
    };

    return userService;
});

function MyCtrl($scope, UserService) {
    $scope.name = UserService.name;
    $scope.updatedname="";
    $scope.changeName=function(data){
        $scope.updateServiceName(data);
    }
    $scope.updateServiceName = function(name){
        UserService.ChangeName(name);
        $scope.name = UserService.name;
    }
}

এমনকি আমাকে পৃষ্ঠের নেভিগেশনগুলির মধ্যে এটি করতে হবে (পৃষ্ঠা রিফ্রেশ নয়)। এটা কি সঠিক?
FutuToad

আমি মনে করি এই উত্তরটি সম্পূর্ণ করার জন্য আমার অংশটি যুক্ত করা updateServiceউচিত , যখন নিয়ামকটি ধ্বংস হয়ে যায় তখন ফোন করা উচিত - $scope.$on('$destroy', function() { console.log('Ctrl destroyed'); $scope.updateServiceName($scope.name); });
শ্বেন্দ্র

10

$ রুটস্কোপ একটি বড় গ্লোবাল ভেরিয়েবল, যা এক-অফ জিনিস বা ছোট অ্যাপ্লিকেশানের জন্য জরিমানা। আপনি যদি আপনার মডেল এবং / অথবা আচরণটি আবদ্ধ করতে চান (এবং সম্ভবত এটি অন্য কোথাও পুনরায় ব্যবহার করতে চান) একটি পরিষেবা ব্যবহার করুন। ওপির উল্লিখিত গুগল গ্রুপ পোস্টের পাশাপাশি https://groups.google.com/d/topic/angular/eegk_lB6kVs/discussion দেখুন


8

কৌনিকটি বাক্সের বাইরে যা খুঁজছে তা সত্যিই সরবরাহ করে না। আপনি যেটি পরে করবেন তা অর্জন করতে আমি কী করব তা হ'ল নিম্নলিখিত অ্যাডগুলি ব্যবহার করুন

ইউআই রাউটার এবং ইউআই রাউটার অতিরিক্ত

এই দুটি আপনাকে রাজ্য ভিত্তিক রাউটিং এবং স্টিকি স্টেটস সরবরাহ করবে, আপনি রাজ্যের মধ্যে ট্যাব করতে পারেন এবং কথা বলার সুযোগ "জীবিত থাকে" হিসাবে সমস্ত তথ্য সংরক্ষণ করা হবে।

উভয়ই ডকুমেন্টেশন চেক করুন যেহেতু এটি বেশ সোজা এগিয়ে রয়েছে, ইউআই রাউটার এক্সট্রাগুলিতেও স্টিকি স্টেটগুলি কীভাবে কাজ করে তার একটি ভাল প্রদর্শন রয়েছে।


আমি দস্তাবেজগুলি পড়েছি তবে ব্যবহারকারীরা ব্রাউজারের পিছনে বোতামটি ক্লিক করলে কীভাবে ফর্ম ইনপুট সংরক্ষণ করবেন তা খুঁজে পেলাম না। দয়া করে আমাকে নির্দিষ্ট করে তুলতে পারেন? ধন্যবাদ!
ডালিবোর

6

আমার একই সমস্যা ছিল, আমি এটিই করেছি: একই পৃষ্ঠায় একাধিক মতামত সহ আমার একটি এসপিএ রয়েছে (এজ্যাক্স ছাড়াই), সুতরাং এটি মডিউলটির কোড:

var app = angular.module('otisApp', ['chieffancypants.loadingBar', 'ngRoute']);

app.config(['$routeProvider', function($routeProvider){
    $routeProvider.when('/:page', {
        templateUrl: function(page){return page.page + '.html';},
        controller:'otisCtrl'
    })
    .otherwise({redirectTo:'/otis'});
}]);

সমস্ত দর্শনের জন্য আমার কাছে কেবলমাত্র একজন নিয়ামক রয়েছে তবে সমস্যাটি প্রশ্নের সমান, নিয়ামক হিসাবে নিম্নলিখিত:

app.factory('otisService', function($http){
    var service = {            
        answers:[],
        ...

    }        
    return service;
});

app.controller('otisCtrl', ['$scope', '$window', 'otisService', '$routeParams',  
function($scope, $window, otisService, $routeParams){        
    $scope.message = "Hello from page: " + $routeParams.page;
    $scope.update = function(answer){
        otisService.answers.push(answers);
    };
    ...
}]);

এখন আমি আমার যে কোনও ভিউ থেকে আপডেট ফাংশনটি কল করতে পারি, মানগুলি পাস করতে এবং আমার মডেলটি আপডেট করতে পারি, অধ্যবসায় ডেটার জন্য আমার এইচটিএমএল 5 অ্যাপ ব্যবহার করার দরকার নেই (এটি আমার ক্ষেত্রে, সম্ভবত অন্যান্য ক্ষেত্রে এইচটিএমএল 5 ব্যবহার করা প্রয়োজন হবে) স্থানীয় স্টোরেজ এবং অন্যান্য স্টাফের মতো এপিআই)।


হ্যাঁ, কবজির মতো কাজ করেছে। আমাদের ডেটা ফ্যাক্টরিটি ইতিমধ্যে কোডেড ছিল এবং আমি কন্ট্রোলারস সিনট্যাক্সটি ব্যবহার করছিলাম, তাই আমি এটিকে আবার স্কোপ নিয়ামকটিতে আবার লিখেছি, যাতে কৌণিক এটিকে নিয়ন্ত্রণ করতে পারে। বাস্তবায়ন খুব সোজা ছিল। এটি প্রথম কৌণিক অ্যাপ্লিকেশন আইআইএম রাইটটিং। tks
egidiocs

2

পরিষেবাগুলির বিকল্প হ'ল মান স্টোর ব্যবহার করা।

আমার অ্যাপের বেসে আমি এটি যুক্ত করেছি

var agentApp = angular.module('rbAgent', ['ui.router', 'rbApp.tryGoal', 'rbApp.tryGoal.service', 'ui.bootstrap']);

agentApp.value('agentMemory',
    {
        contextId: '',
        sessionId: ''
    }
);
...

এবং তারপরে আমার নিয়ামকটিতে আমি কেবলমাত্র মূল্য স্টোরটি উল্লেখ করি। আমি মনে করি না যদি ব্যবহারকারী ব্রাউজারটি বন্ধ করে দেয় তবে এটি জিনিস রাখে।

angular.module('rbAgent')
.controller('AgentGoalListController', ['agentMemory', '$scope', '$rootScope', 'config', '$state', function(agentMemory, $scope, $rootScope, config, $state){

$scope.config = config;
$scope.contextId = agentMemory.contextId;
...

1

সমাধান যা সেই স্কোপের মধ্যে একাধিক স্কোপ এবং একাধিক ভেরিয়েবলের জন্য কাজ করবে

এই পরিষেবাটি অ্যান্টনের উত্তরের ভিত্তিতে তৈরি হয়েছিল, তবে এটি আরও বর্ধিত এবং একাধিক স্কোপ জুড়ে কাজ করবে এবং একই সুযোগে একাধিক স্কোপ ভেরিয়েবলগুলি নির্বাচন করার অনুমতি দেয় allows এটি প্রতিটি স্কোপকে সূচক করার জন্য রুট পথ ব্যবহার করে এবং তারপরে স্কোপ ভেরিয়েবলের নামকে এক স্তর আরও গভীর করে index

এই কোড দিয়ে পরিষেবা তৈরি করুন:

angular.module('restoreScope', []).factory('restoreScope', ['$rootScope', '$route', function ($rootScope, $route) {

    var getOrRegisterScopeVariable = function (scope, name, defaultValue, storedScope) {
        if (storedScope[name] == null) {
            storedScope[name] = defaultValue;
        }
        scope[name] = storedScope[name];
    }

    var service = {

        GetOrRegisterScopeVariables: function (names, defaultValues) {
            var scope = $route.current.locals.$scope;
            var storedBaseScope = angular.fromJson(sessionStorage.restoreScope);
            if (storedBaseScope == null) {
                storedBaseScope = {};
            }
            // stored scope is indexed by route name
            var storedScope = storedBaseScope[$route.current.$$route.originalPath];
            if (storedScope == null) {
                storedScope = {};
            }
            if (typeof names === "string") {
                getOrRegisterScopeVariable(scope, names, defaultValues, storedScope);
            } else if (Array.isArray(names)) {
                angular.forEach(names, function (name, i) {
                    getOrRegisterScopeVariable(scope, name, defaultValues[i], storedScope);
                });
            } else {
                console.error("First argument to GetOrRegisterScopeVariables is not a string or array");
            }
            // save stored scope back off
            storedBaseScope[$route.current.$$route.originalPath] = storedScope;
            sessionStorage.restoreScope = angular.toJson(storedBaseScope);
        },

        SaveState: function () {
            // get current scope
            var scope = $route.current.locals.$scope;
            var storedBaseScope = angular.fromJson(sessionStorage.restoreScope);

            // save off scope based on registered indexes
            angular.forEach(storedBaseScope[$route.current.$$route.originalPath], function (item, i) {
                storedBaseScope[$route.current.$$route.originalPath][i] = scope[i];
            });

            sessionStorage.restoreScope = angular.toJson(storedBaseScope);
        }
    }

    $rootScope.$on("savestate", service.SaveState);

    return service;
}]);

আপনার অ্যাপ্লিকেশন মডিউলে আপনার রান ফাংশনে এই কোডটি যুক্ত করুন:

$rootScope.$on('$locationChangeStart', function (event, next, current) {
    $rootScope.$broadcast('savestate');
});

window.onbeforeunload = function (event) {
    $rootScope.$broadcast('savestate');
};

আপনার নিয়ামকটিতে পুনরুদ্ধারস্কোপ পরিষেবাটি ইনজেক্ট করুন (নীচের উদাহরণে):

function My1Ctrl($scope, restoreScope) {
    restoreScope.GetOrRegisterScopeVariables([
         // scope variable name(s)
        'user',
        'anotherUser'
    ],[
        // default value(s)
        { name: 'user name', email: 'user@website.com' },
        { name: 'another user name', email: 'anotherUser@website.com' }
    ]);
}

উপরের উদাহরণটি $ স্কোপ.ইউসারকে স্টোরেজ মানটির সূচনা করবে, অন্যথায় প্রদত্ত মানটিতে ডিফল্ট হবে এবং সেটিকে সংরক্ষণ করবে। পৃষ্ঠাটি বন্ধ হয়ে থাকলে, রিফ্রেশ করা হয়েছে বা রুটটি পরিবর্তিত হলে সমস্ত নিবন্ধিত স্কোপ ভেরিয়েবলের বর্তমান মানগুলি সংরক্ষণ করা হবে এবং পরের বার রুট / পৃষ্ঠাটি দেখার পরে পুনরুদ্ধার করা হবে।


আমি যখন আমার কোডটিতে এটি যুক্ত করি তখন আমি একটি ত্রুটি পেয়েছি "টাইপ এরির: অপরিজ্ঞাত 'সম্পত্তি' স্থানীয়রা 'পড়তে পারি না" আমি কীভাবে এটি ঠিক করব? @ ব্রেট
মাইকেল মাহনি

আপনি কি আপনার রুটগুলি পরিচালনা করতে কৌনিক ব্যবহার করছেন? আমি "না" অনুমান করছি যেহেতু $ রুট কন্টেন্টটি পূর্বনির্ধারিত বলে মনে হচ্ছে।
ব্রেট পেনিংস

হ্যাঁ, কৌনিকটি আমার রাউটিং পরিচালনা করছে। রাউটিংয়ে আমার যা আছে তার একটি নমুনা এখানে দেওয়া হয়েছে: JBenchApp.config ([['$ রুটপ্রভাইডার', '$ লোকেশনপ্রভাইডার', ফাংশন ($ রুটপ্রভাইডার, $ লোকেশনপ্রভাইডার)) {$ রুটপ্রভাইডার। যখন ('/ ড্যাশবোর্ড', {টেমপ্লেটআরল: ' পার্টিয়ালস / ড্যাশবোর্ড এইচটিএমএল ', নিয়ামক:' জেবেঞ্চসিআরটিএল '})
মাইকেল মহনি

আমার একমাত্র অনুমান আপনার অ্যাপ্লিকেশনটি কনফিগার করার আগে আপনার নিয়ামকটি চলমান। যে কোনও উপায়ে, আপনি সম্ভবত $ রুটের পরিবর্তে $ অবস্থান ব্যবহার করে এবং তারপরে রুটে এটি অ্যাক্সেস না করে নিয়ামকের কাছ থেকে স্কোপ দিয়ে। পরিবর্তে আপনার পরিষেবার জন্য gist.github.com/brettpennings/ae5d34de0961eef010c6 ব্যবহার করার চেষ্টা করুন এবং আপনার নিয়ামকটিতে পুনরুদ্ধারকোষ.গেটঅরজিস্টারস্কোপ ভ্যারিয়েবলগুলির তৃতীয় প্যারামিটার হিসাবে $ স্কোপটিতে পাস করুন। যদি এটি আপনার পক্ষে কাজ করে তবে আমি সম্ভবত এটি আমার নতুন উত্তরটি দিতে পারি। শুভকামনা!
ব্রেট পেনিংস

1

আপনি কোনও পরিষেবাতে বা $locationChangeStartপূর্বের মানটি সঞ্চয় করতে ইভেন্টটি ব্যবহার করতে পারেন $rootScope। আপনি যখন ফিরে আসবেন, কেবলমাত্র আগের সমস্ত সঞ্চিত মানগুলি আরম্ভ করুন। এখানে একটি দ্রুত ডেমো ব্যবহার করা হচ্ছে $rootScope

এখানে চিত্র বর্ণনা লিখুন

var app = angular.module("myApp", ["ngRoute"]);
app.controller("tab1Ctrl", function($scope, $rootScope) {
    if ($rootScope.savedScopes) {
        for (key in $rootScope.savedScopes) {
            $scope[key] = $rootScope.savedScopes[key];
        }
    }
    $scope.$on('$locationChangeStart', function(event, next, current) {
        $rootScope.savedScopes = {
            name: $scope.name,
            age: $scope.age
        };
    });
});
app.controller("tab2Ctrl", function($scope) {
    $scope.language = "English";
});
app.config(function($routeProvider) {
    $routeProvider
        .when("/", {
            template: "<h2>Tab1 content</h2>Name: <input ng-model='name'/><br/><br/>Age: <input type='number' ng-model='age' /><h4 style='color: red'>Fill the details and click on Tab2</h4>",
            controller: "tab1Ctrl"
        })
        .when("/tab2", {
            template: "<h2>Tab2 content</h2> My language: {{language}}<h4 style='color: red'>Now go back to Tab1</h4>",
            controller: "tab2Ctrl"
        });
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-route.js"></script>
<body ng-app="myApp">
    <a href="#/!">Tab1</a>
    <a href="#!tab2">Tab2</a>
    <div ng-view></div>
</body>
</html>

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.